#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Spinner.H>
#include <FL/Fl_Multiline_Output.H>
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_Box.H>
#include <FL/x.H>
#include <cstdlib>
#include <math.h>
#include <iostream>
#include <string.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

// This was put together by jon.cooper@ucl.ac.uk from tutorials and 
// code snippets on the internet and with help from the FLTK forum. 

class SimpleWindow:public Fl_Window{
// This is to do with inheritance!
// Fl_Window = base class/super-class, SimpleWindow = derived class/sub-class.
// Saying public after the : means that public members of Fl_Window
// become public members of SimpleWindow, p.140, Hubbard.

public: 
SimpleWindow(int w, int h, const char* title);
~SimpleWindow();
// ~ is the destructor which kills SimpleWindow when its not needed any more. 

Fl_Button* load;
Fl_Button* help;
Fl_Button* quit;
Fl_Button* prepare;
Fl_Button* mainrun;
Fl_Input* inpid;
Fl_Input* inpseq;
Fl_Multiline_Output* out;
Fl_File_Chooser* chooser;
Fl_Spinner *spinner;
const char* fileread;
char* fred;
char* s1;
char* s2;
char* sid;
char* batfile_main;
char* cat; 
char* addmap;
char* addprep;
char* addrun;

// Declare the call-back and other functions. 

//private: 

static void cb_chooser(Fl_Widget*, void*);
inline void cb_chooser_i();
//static => the function cb_chooser applies to all widgets in the class. 
//inline function sets up an abbreviation for the command. Ditto for below.
static void cb_prepare(Fl_Widget*, void*);
inline void cb_prepare_i();
static void cb_mainrun(Fl_Widget*, void*);
inline void cb_mainrun_i();
// inpchk checks for user input before allowing prepare or main run. 
static void cb_inpchk(Fl_Widget*, void*);
inline void cb_inpchk_i();
//inline functions not needed for cb_quit and cb_help.
static void cb_quit(Fl_Widget*, void*);
static void cb_help(Fl_Widget*, void*);
// Map handling functions.
static void xplor_map_handler(char* &fred, char* s1, char* sid, char* &s2);
static void ccp4_map_handler(char* &fred, char* s1, char* sid, char* &s2);
};

// Set up a class for the input widgets with a right-button paste method. 

class InPaste : public Fl_Input {
    static void Paste_CB(Fl_Widget*, void *userdata) {
//        printf("*** PASTE ***\n");
        InPaste *in = (InPaste*)userdata;
        Fl::paste(*in,1);
    }
public:
    int handle(int e) {
        switch (e) {
            case FL_PUSH:
                // RIGHT MOUSE PUSHED? Popup menu on right click
                if ( Fl::event_button() == FL_RIGHT_MOUSE ) {
                    Fl_Menu_Item rclick_menu[] = {
                        { "Paste",  0, Paste_CB, (void*)this },
                        { 0 }
                    };
                    const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0);
                    if ( m ) m->do_callback(0, m->user_data());
                    return(1);          // (tells caller we handled this event)
                }
                break;
            case FL_RELEASE:
                // RIGHT MOUSE RELEASED? Mask it from Fl_Input
                if ( Fl::event_button() == FL_RIGHT_MOUSE ) {
                    return(1);          // (tells caller we handled this event)
                }
                break;
        }
        return(Fl_Input::handle(e));    // let Fl_Input handle all other events
    }
    InPaste(int X,int Y,int W,int H,const char*L=0):Fl_Input(X,Y,W,H,L) {
    }
};

// End of paste method. 

int main (){
	SimpleWindow win(600,400," MAIDaid");
// main calls the SimpleWindow function (defined below) and sends win to it!?
	return Fl::run();
//FLTK documentation: "A normal program will end main() with return Fl::run();".
}

SimpleWindow::SimpleWindow(int w, int h, const char* title):Fl_Window(w,h,title){
// defines the SimpleWindow function as a class::function sort of thing.

begin();
load = new Fl_Button(30,15,430,30,"Click to choose map file (CCP4 or X-PLOR/CNS ASCII format)");
// new allocates memory for load which is a pointer to Fl_Button.  
load->callback(cb_chooser, this);
// invoke the callback function of chooser. 

help = new Fl_Button(490,40,80,70,"Help");
help->callback(cb_help, this);

// input and output widgets.

inpid = new InPaste(270,60,100,30,"Identifier for this run ");
inpid->when(FL_WHEN_CHANGED);
inpid->callback(cb_inpchk, this);

spinner = new Fl_Spinner(400,100,60,40,"Electron density cutoff for map skeletonisation  \n e.g. 1.4 for good maps, 1.2 for poor maps  "); 
spinner->value(1.4);
spinner->maximum(2.0);
spinner->minimum(1.0);
spinner->step(0.1);

inpseq = new InPaste(170,160,400,50,"Paste the sequence in\n single letter code here");
inpseq->when(FL_WHEN_CHANGED);
inpseq->callback(cb_inpchk, this);

out = new Fl_Multiline_Output(30,230,540,120,"Log");

prepare = new Fl_Button(240,360,120,30,"Prepare Files");
prepare->deactivate(); 
prepare->callback(cb_prepare, this);

mainrun = new Fl_Button(430,360,120,30,"Main Run");
mainrun->deactivate(); 
mainrun->callback(cb_mainrun, this);

quit = new Fl_Button(50,360,120,30,"Quit");
quit->callback(cb_quit, this);

icon((char*)LoadIcon(fl_display, MAKEINTRESOURCE(101)));

end();
resizable(this);
show();
}

// Call the destructor.
SimpleWindow::~SimpleWindow(){} 

// * * * * * * File chooser callback function * * * * * *

void SimpleWindow::cb_chooser(Fl_Widget* o, void* v){
// defines the cb_chooser function.
((SimpleWindow*)v)->cb_chooser_i();}
// invoke the cb_chooser_i function of v (which points to SimpleWindow)!?

void SimpleWindow::cb_chooser_i(){
// define the cb_chooser_i function. 

Fl_File_Chooser *chooser = new Fl_File_Chooser(".", "Maps (*map*)", 0, " Select map (must be CCP4 or X-PLOR/CNS ASCII format)");
	 chooser->show();
while(chooser->shown())
      Fl::wait(); 

fileread = chooser->value();
out->value(fileread);

if ( inpid->value()[0] != 0 && inpseq->value()[0] != 0) {
            prepare->activate(); }
}

// * * * * * * Callback function to prepare the MAID files * * * * * *

void SimpleWindow::cb_prepare(Fl_Widget* o, void* v){
((SimpleWindow*)v)->cb_prepare_i();}

void SimpleWindow::cb_prepare_i(){

float cutoff = spinner->value();

fred=(char*)malloc(strlen(fileread)+1);
strcpy(fred,fileread);

  const string& str=fred;
  size_t found;
  found=str.find_last_of("/\\");
  string str1=str.substr(0,found); 
  string str2=str.substr(found+1);

size_t posi = 0;
  while((posi = str1.find("/", posi)) != std::string::npos)
  {
     str1.replace(posi, 1, "\\");
     posi += 1;
  }

s1 = (char*)str1.c_str();
s2 = (char*)str2.c_str();

cat = (char*)malloc(strlen(fred)+2*strlen(s1)+strlen(s2)+100);
strcpy(cat,"Selected: ");
strcat(cat,fred);
strcat(cat,"\nMap folder: ");
strcat(cat, s1);
strcat(cat,"\nMap file: ");
strcat(cat, s2);
strcat(cat,"\nThe MAID files have been prepared in ");
strcat(cat, s1);
strcat(cat,"\n"); 
out->value(cat);

char const *id = inpid->value();

char const *seqred = inpseq->value();
int siz = inpseq->size();
const string& stred=seqred;

char s[siz];
	  strcpy(s, stred.c_str()); 

//    printf( "Before non-AA's removed: '%s'\n", s );
   
    int q;
    for( q=0; s[q]!='\0'; ++q ) {
    s[q]=toupper(s[q]);
    } 

    int i, j, nres=0;
    for( i=0; s[i]!='\0'; ++i )
    {
while(s[i]!='A' &&s[i]!='C' &&s[i]!='D' &&s[i]!='E' &&s[i]!='F' 
    &&s[i]!='G' &&s[i]!='H' &&s[i]!='I' &&s[i]!='K' &&s[i]!='L' 
    &&s[i]!='M' &&s[i]!='N' &&s[i]!='P' &&s[i]!='Q' &&s[i]!='R' 
    &&s[i]!='S' &&s[i]!='T' &&s[i]!='V' &&s[i]!='W' &&s[i]!='Y' &&s[i]!='\0')
// Copy everything to the right of non-AA characters over them.
        {
            j=i;
            while(s[j]!='\0')
            {
                s[j]=s[j+1];
                ++j;
	    }
 	}
    ++nres;
    }

//    printf( "After non-AA's removed: '%s'\n", s );

const string& strid=id;
sid = (char*)strid.c_str();
char *seqfil = (char*)malloc(strlen(s1)+strlen(sid)+30);
strcpy(seqfil,s1);
strcat(seqfil,"\\");
strcat(seqfil,sid);
strcat(seqfil,".maidpdbsequence");
   FILE * pFile;
   pFile = fopen (seqfil,"w");
   int n=0, m=0;
fprintf (pFile, "1\n");
for(n=0; n<nres; n+=60){
for(m=n; m<60+n && m<nres; ++m){
  	fprintf (pFile, "%c", s[m]);}
  	fprintf (pFile, "\n");
}
fclose (pFile);
inpseq->value(s);

// * * * * * * Start of map format checking part * * * * * * 

char hdr1 [2];
FILE * mapFile;
mapFile = fopen (fred,"r");
fgets (hdr1, 2 , mapFile); 
fclose(mapFile);

addmap = (char*)malloc(100);

char *axestest = (char*)malloc(10);
strcpy(axestest,"nogo");

if (hdr1[0]=='\n'){ 
strcpy(addmap, "The map is in X-PLOR format and will be normalised, if necessary.\n"); 

SimpleWindow::xplor_map_handler(fred, s1, sid, s2);
}

else { 
strcpy(addmap, "The map will be converted from CCP4 to X-PLOR format and normalised.\n"); 
	
SimpleWindow::ccp4_map_handler(fred, s1, sid, s2); // convert map to X-PLOR format
	
if(*fred==*axestest){out->value("\n\nPROBLEM: axes are in the wrong order or map file format is incorrect. \n\nRe-calculate the map with CCP4 defaults."); 
prepare->deactivate();}
	
else SimpleWindow::xplor_map_handler(fred, s1, sid, s2); // process the X-PLOR map which fred now points to.
}

// * * * * * * End of map format checking part * * * * * * 


if(*fred!=*axestest){

// Program determines the directory in which it exists (exestr) and 
// writes a batch file in the directory where the user files exist (s1).  
// The batch file runs the executable in the program directory, taking 
// instructions from an input file which is written in the user folder.

    char buffer[MAX_PATH];
    GetModuleFileName( NULL, buffer, MAX_PATH );
    string::size_type pos = string( buffer ).find_last_of( "\\/" );
    string exestr=string( buffer ).substr( 0, pos); 

const string& stridcopy=id;
char* sidcopy = (char*)stridcopy.c_str();
const string& strexestr=exestr;
char* exedir = (char*)strexestr.c_str();
char *bat = (char*)malloc(strlen(sidcopy)+strlen(exedir)+strlen(s1)+90);
strcpy (bat, "cd /d \"");
strcat (bat, s1);
strcat (bat, "\\\"\n\"");
strcat (bat, exedir);
strcat(bat,"\\maidbatch.exe\" ");
strcat(bat, sidcopy);
strcat(bat, " setup < maidsetup.inp > maidsetup.log");

char *mainbat = (char*)malloc(strlen(sidcopy)+strlen(exedir)+strlen(s1)+100);
strcpy (mainbat, "cd /d \"");
strcat (mainbat, s1);
strcat (mainbat, "\\\"\nstart taskmgr\n\"");
strcat (mainbat, exedir);
strcat(mainbat,"\\maidbatch.exe\" ");
strcat(mainbat, sidcopy);
strcat(mainbat, ".maid complete > maidcomplete.log");

char *ctl = (char*)malloc(strlen(s1)+40);
strcpy(ctl,s1);
strcat(ctl,"\\maidsetup.inp");
   FILE * iFile;
   iFile = fopen (ctl,"w");
   fprintf (iFile, "%s\nno\n", s2);
   fprintf (iFile, "%.1f", cutoff);
   fclose (iFile);

char *batfile_setup = (char*)malloc(strlen(s1)+30);
strcpy(batfile_setup,s1);
strcat(batfile_setup,"\\maidsetup.bat");
   FILE * bFile;
   bFile = fopen (batfile_setup,"w");
   fprintf (bFile, "%s", bat);
   fclose (bFile);

batfile_main = (char*)malloc(strlen(s1)+40);
strcpy(batfile_main,s1);
strcat(batfile_main,"\\maidcomplete.bat");
   FILE * mFile;
   mFile = fopen (batfile_main,"w");
   fprintf (mFile, "%s", mainbat);
   fclose (mFile);
   
//system(batfile_setup);
//
//ShellExecute( NULL, "open",         
//    batfile_setup, // program to launch
//    NULL,  // parms (%1 and %2 in the batch file)
//    s1,        // default dir for the batch
//    SW_SHOWNORMAL 
//);

SHELLEXECUTEINFO rSEI ={0};
rSEI.cbSize=sizeof( rSEI );
rSEI.lpVerb= "open";
rSEI.lpFile= batfile_setup;
rSEI.lpParameters= 0;
rSEI.nShow = SW_HIDE;
rSEI.fMask = SEE_MASK_NOCLOSEPROCESS;

ShellExecuteEx( &rSEI );   // you should check for an error here
while( TRUE ) {
    DWORD nStatus= MsgWaitForMultipleObjects(
                1, &rSEI.hProcess, FALSE, 
                INFINITE, QS_ALLINPUT   // drop through on user activity 
    );
    if ( nStatus == WAIT_OBJECT_0 ) {  // done: the program has ended
        break;
    }
    MSG msg;     // else process some messages while waiting...
    while( PeekMessage(&msg,NULL,0,0,PM_REMOVE) ){
        DispatchMessage( &msg );
    }
}  // launched process has exited

addprep = (char*)malloc(strlen(cat)+strlen(addmap)+100);
strcpy(addprep,cat);
strcat(addprep,addmap);
strcat(addprep,"Check new files in the map folder before clicking the Main Run button.\n"); 
out->value(addprep);
mainrun->activate(); 

free(fred);
free(cat);
free(seqfil);
free(addmap);
free(axestest);
free(bat);
free(mainbat);
free(ctl);
free(batfile_setup);

}
}

// * * * * * * The callback function for the main run * * * * * *

void SimpleWindow::cb_mainrun(Fl_Widget* o, void* w){
((SimpleWindow*)w)->cb_mainrun_i();}

void SimpleWindow::cb_mainrun_i(){

ShellExecute( NULL, "open",         
    batfile_main, // program to launch
    NULL,  // parms (%1 and %2 in the batch file)
    s1,        // default dir for the batch
    SW_HIDE 
);
mainrun->deactivate(); 
prepare->deactivate(); 

addrun = (char*)malloc(strlen(addprep)+100);
strcpy(addrun,addprep);
strcat(addrun,"maidbatch.exe running & may take several hours - check Windows Task Manager.\n"); 
out->value(addrun);

free(addprep);
free(batfile_main);
free(addrun);

}

// The callback function for quit.
void SimpleWindow::cb_quit(Fl_Widget* o, void* v){
	((SimpleWindow*)v)->hide();}

// Callback function to activate prepare button only after user input.
void SimpleWindow::cb_inpchk(Fl_Widget* o, void* z){
	((SimpleWindow*)z)->cb_inpchk_i();}

void SimpleWindow::cb_inpchk_i(){
if ( inpid->value()[0] != 0 && inpseq->value()[0] != 0 && out->value()[0] != 0) {
            prepare->activate();
     }
}

// The callback function for help. 
void SimpleWindow::cb_help(Fl_Widget* o, void* v){
Fl_Window *helpwin=new Fl_Window(640,660," Help on MAIDaid");
Fl_Box *helpbox=new Fl_Box(FL_NO_BOX,10,10,620,640,"- The main steps in running MAIDaid -\n\n\
\
1. Firstly, select the map file using the file browser that is started by clicking the top button. The map has to be either in CCP4 format or in XPLOR/CNS ASCII format. \n\nBy default, maps made with CCP4 will cover the asymmetric unit whereas those made by PHENIX cover the unit cell. Since both of these situations may not be ideal for MAID, it can be better to extend the map to cover a preferred region e.g. by building a dummy water molecule roughly in the middle of the protein density and saving the water molecule coordinates in a PDB file. Subsequently using PHENIX or CCP4 to calculate the map around this water molecule with say a 35 - 40 Angstrom border may give better results. \n\nYou can add your map folder to 'Favorites' to save time with repeat runs. \n\n\
\
2. Enter a short identifier for this run, without spaces. Files will be produced by MAID in the same folder as the map and they will carry the given identifier as a prefix. \n\n\
\
3. Choose an electron density cut-off value for skeletonisation of contiguous regions of the map, e.g. 1.4 for good maps, 1.2 for poor maps. \n\n\
\
4. Paste in the amino acid sequence in single letter code using the right mouse button or Control V. Non-standard characters and numbers can be left in since the GUI will attempt to remove them. \n\n\
\
5. Click the \"Prepare Files\" button to generate the batch and input files needed to run MAID. MAID will run briefly in \"SETUP\" mode to produce the files it needs for the next step. \n\n\
\
6. Click the \"Main Run\" button to start the \"COMPLETE\" option of MAID which may take several hours to finish. During this time, MAIDaid itself may be closed, but the background maidbatch.exe process, which is visible in the Windows Task Manager, must be left running. \n\n\
\
7. As it runs, maidbatch will produce different pdb files in the following order: \"trace\" (finds the sheets and helices), \"extend\" (assigns the amino acid resides and extends through the loops) and \"expand\" (groups the pdb fits into segments). Although it may crash before all of the files are produced, it should produce something useful! An explanation of the output files can be found in the MAID documentation which also has details of parameters in the input files that the user can change to re-run it in batch mode, if required. \n\n\
\
8. To help Coot display PDB files produced by MAID, you may need to renumber all of the residues with PDBSET and add the appropriate unit cell and symmetry information.");
helpwin->resizable(helpbox);
helpbox->align(FL_ALIGN_WRAP);
helpwin->end();
helpwin->show();
Fl::run();
}


void SimpleWindow::xplor_map_handler(char* &fred, char* s1, char* sid, char* &s2){

// * * * * * * X-PLOR MAP HANDLING PART STARTS HERE * * * * * *

  char hdr1[100], hdr2[100], hdr3[100], hdr4[6][300], hdr5[100]; 
  char hdr6[100], hdr7[100], xyz[10];
  int na, amin, amax, nb, bmin, bmax, nc, cmin, cmax, nsect;
  char cell[100]; 
  float rho=0, mapav=0, maptot=0, sd=0;
  FILE * mapFile;
  FILE * normFile;

mapFile = fopen (fred,"r");

fgets (hdr1, 2 , mapFile); 
fgets (hdr2, 9, mapFile);
int ntitl=atoi(hdr2);

fgets (hdr3, 10, mapFile);
int nt;
for(nt=1; nt<=ntitl; nt++){
fgets (hdr4[nt], 300 , mapFile);}

fscanf(mapFile, "%d%d%d%d%d%d%d%d%d\n", &na, &amin, &amax, &nb, &bmin, &bmax, &nc, &cmin, &cmax);
fgets (cell, 100, mapFile); 

fscanf(mapFile, "%s", xyz);

// Flags-up the start of the density values.
long mapstart=ftell(mapFile);
// Scans the map values to get the average density.
int h, k, l, num=0;
int lmax=cmax-cmin;
int kmax=bmax-bmin;
int hmax=amax-amin;

for(l=0; l<=lmax; l++){
fscanf(mapFile, "%d", &nsect);

for(k=0; k<=kmax; k++){
for(h=0; h<=hmax; h++){
    fscanf(mapFile, "%E", &rho);
num++;
//printf("density=%e \n", rho);
maptot=rho+maptot;
}}}
mapav=maptot/num;
//printf("Total density=%e Number of points=%d Mean density=%e\n", maptot, num, mapav);

// Goes back to start of density values. 
fseek(mapFile, mapstart, SEEK_SET);
// Scans the map values to get standard deviation from the mean.
num=0;
for(l=0; l<=lmax; l++){
fscanf(mapFile, "%d", &nsect);

for(k=0; k<=kmax; k++){
for(h=0; h<=hmax; h++){
    fscanf(mapFile, "%E", &rho);
sd=sd+pow((rho-mapav),2);
num++;
maptot=rho+maptot;
}}}
sd=sqrt(sd/num);
//printf("SD=%e Number of points=%d \n", sd, num);

// Idea is that if the map is normalised it will drop out here 
// but if it is not, it will normalise the density values.

if(fabs(mapav)>0.1 || fabs(sd-1)>0.1) { 
	
// Open New Map File (nmf). 
char *nmf = (char*)malloc(strlen(s1)+strlen(sid)+30);
strcpy(nmf,s1);
strcat(nmf,"\\");
strcat(nmf,sid);
strcat(nmf,"_normalised.map");
normFile = fopen (nmf,"w");

// Change s2 pointer to the normalised map filename.
char* s2copy = (char*)malloc(strlen(sid)+30);
strcpy(s2copy,sid);
strcat(s2copy,"_normalised.map");
s2=s2copy;

// Writes the header info to the new map file.
fprintf(normFile, "%s", hdr1);
fprintf(normFile, "%s", hdr2);
fprintf(normFile, "%s", hdr3);

int nt;
for(nt=1; nt<=ntitl; nt++){fprintf(normFile, "%s", hdr4[nt]);}

fprintf(normFile, "%8d%8d%8d%8d%8d%8d%8d%8d%8d\n", na, amin, amax, nb, bmin, bmax, nc, cmin, cmax);
fprintf(normFile, "%73s", cell);
fprintf(normFile, "%s\n", xyz);

// Goes back to top of density values, reads and normalised them. 
fseek(mapFile, mapstart, SEEK_SET);
for(l=0; l<=lmax; l++){
fscanf(mapFile, "%d", &nsect);
fprintf(normFile, "%8d\n", nsect);
int ncol=1;
for(k=0; k<=kmax; k++){
for(h=0; h<=hmax; h++){
    fscanf(mapFile, "%E", &rho);
    rho=(rho-mapav)/sd;

// Correct the Windows three digit exponent.
char rhom[13];
sprintf (rhom, "%13.5E", rho);
rhom[11]=rhom[12];
rhom[12]=rhom[13];
rhom[13]=' ';

// Writes the normalised density values out formatted. 
if (ncol==6){fprintf(normFile, "%12s\n", rhom); ncol=1;}
else {fprintf(normFile, "%12s", rhom); ncol++;}}}
if(ncol!=1){fprintf(normFile, "\n");}}

// Rest is for the map footer.
// Note file pointer will be at end of last line of map (hence dummy hdr5)";
fgets (hdr5, 20 , mapFile); 
fgets (hdr6, 20 , mapFile); 
fprintf(normFile, "%s", hdr6);
fgets (hdr7, 30, mapFile);
fprintf(normFile, "%s", hdr7);

fclose(mapFile);
fclose(normFile);
}
// * * * * * * END OF X-PLOR MAP HANDLING PART * * * * * *
}

// * * * * * * START OF CCP4 MAP HANDLING PART * * * * * *

void SimpleWindow::ccp4_map_handler(char* &fred, char* s1, char* sid, char* &s2){

  FILE * cFile;
  FILE * xFile;
  int grid[10];
  float cell[6];
  int order[3];
  float mimameden[3];
  int symbits[3];
  float skewmt[12];
  int future_echo[15];
  char* mapword; 
  char* machine_junk; 
  float rms[1];
  int numlabel[1];
  char* labels;
  char* symops;
  int result;

cFile = fopen (fred,"rb"); // open CCP4 map

// Copy the file headers into arrays, ignoring some. 
result = fread (grid,4,10,cFile);
//printf("%i\n", result);
//for (int i = 0; i < 10; i++) printf("%i ", grid[i]);
  
result = fread (cell,4,6,cFile);
//printf("\n%i\n", result);
//for (int i = 0; i < 6; i++) printf("%f ", cell[i]);

result = fread (order,4,3,cFile);
//printf("\n%i\n", result);
//for (int i = 0; i < 3; i++) printf("%i ", order[i]);
  
result = fread (mimameden,4,3,cFile);
//printf("\n%i\n", result);
//for (int i = 0; i < 3; i++) printf("%f ", mimameden[i]);

result = fread (symbits,4,3,cFile);
//printf("\n%i\n", result);
//for (int i = 0; i < 3; i++) printf("%i ", symbits[i]);
  
result = fread (skewmt,4,12,cFile);
//printf("\n%i\n", result);
//for (int i = 0; i < 12; i++) printf("%f ", skewmt[i]);

result = fread (future_echo,4,15,cFile);
//printf("\n%i\n", result);
//for (int i = 0; i < 15; i++) printf("%i ", future_echo[i]);

mapword = (char*) malloc (10);
result = fread (mapword,4,1,cFile);
//printf("\n%i\n", result);
//printf("%s ", mapword);

machine_junk = (char*) malloc (10);
result = fread (machine_junk,4,1,cFile);
//printf("\n%i\n", result);
//printf("%s ", machine_junk);

result = fread (rms,4,1,cFile);
//printf("\n%i\n", result);
//printf("%f ", rms[0]);

result = fread (numlabel,4,1,cFile);
//printf("\n%i\n", result);
//printf("%i ", numlabel[0]);

labels = (char*) malloc (850);
fread (labels,4,200,cFile);
//printf("\n%i\n", result);
//printf("%s ", labels);

symops = (char*) malloc (symbits[1]+50);
result = fread (symops,1,symbits[1],cFile);
//printf("\n%i\n", result);
//printf("%s ", symops);

//Prepare map file name. 
char *nxmf = (char*)malloc(strlen(s1)+strlen(sid)+30);
strcpy(nxmf,s1);
strcat(nxmf,"\\");
strcat(nxmf,sid);
strcat(nxmf,"_xplor.map");


if (order[0]==2 && order[1]==1 && order[2]==3){ 
// Start of normal space group stuff i.e. maps with Z-sections. 

// Open New X-PLOR Map File (nxmf). 
xFile = fopen (nxmf,"w");
// Change fred pointer to the new XPLOR map filename.
fred = nxmf;
// Write out the X-PLOR map dummy header. 
fprintf(xFile, "\n       1\n REMARKS Map converted from CCP4 to X-PLOR ASCII format by MAIDaid.\n" );

// Write out the grid info (No div. on axis, min and max grid pts).
int na=grid[7];
int amin=grid[5];
int amax=amin+grid[1]-1;

int nb=grid[8];
int bmin=grid[4];
int bmax=bmin+grid[0]-1;

int nc=grid[9];
int cmin=grid[6];
int cmax=cmin+grid[2]-1;

fprintf(xFile, "%8d%8d%8d%8d%8d%8d%8d%8d%8d\n", na, amin, amax, nb, bmin, bmax, nc, cmin, cmax);

// Write out the cell correcting the Windows 3 digit exponent.

for(int c=0; c<6; c++){
char Ecell[13];
sprintf (Ecell, "%13.5E", cell[c]);
Ecell[11]=Ecell[12];
Ecell[12]=Ecell[13];
Ecell[13]=' ';
fprintf(xFile, "%12s", Ecell);}

fprintf(xFile, "\nZYX\n");

// Read the map values and transpose each section. 

int hmax=grid[0];
int kmax=grid[1];
int lmax=grid[2];
float rho[kmax][hmax];

for(int l=0; l<lmax; l++){
for(int k=0; k<kmax; k++){
for(int h=0; h<hmax; h++){
    fread(&rho[k][h],4,1, cFile);
//printf("%f ", rho);
}
//printf("\n");
}
// Write out section number. 
fprintf(xFile, "%8d\n", l);

int ncol=1;
for(int h=0; h<hmax; h++){
for(int k=0; k<kmax; k++){

// Correct the Windows 3 digit exponent. 	
char rhom[13];
sprintf (rhom, "%13.5E", rho[k][h]);
rhom[11]=rhom[12];
rhom[12]=rhom[13];
rhom[13]=' ';

// Writes the density values out in X-PLOR ASCII format. 
if (ncol==6){fprintf(xFile, "%12s\n", rhom); ncol=1;}
else {fprintf(xFile, "%12s", rhom); ncol++;}}}
if(ncol!=1){fprintf(xFile, "\n");}}

// Write dummy map footer and close the files.
fprintf(xFile, "   -9999\n  0.00000E+00 1.00000E+00");
fclose (xFile);
fclose (cFile);
} // End of normal space group stuff.


// Check for monoclinic and P1 where axis order is Z=fast, X=medium, Y=slow.

else if (order[0]==3 && order[1]==1 && order[2]==2){ 
// Handle space groups with Y-sections. 
	
// Open New X-PLOR Map File (nxmf). 
xFile = fopen (nxmf,"w");
// Change fred pointer to the new XPLOR map filename.
fred = nxmf;
// Write out the X-PLOR map dummy header. 
fprintf(xFile, "\n       1\n REMARKS Map converted from CCP4 to X-PLOR ASCII format by MAIDaid.\n" );

// Write out grid and get No sections: nas, nbs, ncs.
int na=grid[7];
int amin=grid[5];
int nas=grid[1];
int amax=amin+nas-1;

int nb=grid[8];
int bmin=grid[6];
int nbs=grid[2];
int bmax=bmin+nbs-1;

int nc=grid[9];
int cmin=grid[4];
int ncs=grid[0];
int cmax=cmin+ncs-1;

fprintf(xFile, "%8d%8d%8d%8d%8d%8d%8d%8d%8d\n", na, amin, amax, nb, bmin, bmax, nc, cmin, cmax);

// Write out the cell correcting for Windows 3 digit exponent.

for(int c=0; c<6; c++){
char Ecell[13];
sprintf (Ecell, "%13.5E", cell[c]);
Ecell[11]=Ecell[12];
Ecell[12]=Ecell[13];
Ecell[13]=' ';
fprintf(xFile, "%12s", Ecell);}

fprintf(xFile, "\nZYX\n");

// Loop through the density values which start 'here'.
long mapstart=ftell(cFile);
float monorho[1];

// Index cc is the section number on Z while index c 
// increments to pick up each point in that section.

for(int cc=0; cc<ncs; cc++){
	fprintf(xFile, "%8d\n", cc);
	int ncol=1;
for(int c=0; c<ncs*nas*nbs; c+=ncs){
//printf("%i ", c+cc); 
fseek(cFile, mapstart+(cc+c)*4, SEEK_SET); 
fread(&monorho[0],4,1, cFile);
    
// Correct Windows 3 digit exponent.
char rhom[13];
sprintf (rhom, "%13.5E", monorho[0]);
rhom[11]=rhom[12];
rhom[12]=rhom[13];
rhom[13]=' ';

// Writes the density values out in X-PLOR ASCII format. 
if (ncol==6){fprintf(xFile, "%12s\n", rhom); ncol=1;}
else {fprintf(xFile, "%12s", rhom); ncol++;}}
if(ncol!=1){fprintf(xFile, "\n");}}

// Write dummy map footer and close the files.
fprintf(xFile, "   -9999\n  0.00000E+00 1.00000E+00");
fclose (xFile);
fclose (cFile);

} // End of 'monoclinic' part. 

// Checking for disallowed fast, medium and slow axis order.
else {char *nogo = (char*)malloc(10);
strcpy(nogo,"nogo");
fred=nogo;
fclose (cFile);
}

free(mapword);
free(machine_junk);
free(labels);
free(symops);
}
