home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Educational / RasMol / Source / script.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-10  |  43.4 KB  |  1,509 lines

  1. /* script.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, August 1995
  4.  * Version 2.6
  5.  */
  6. #define SCRIPT
  7. #include "rasmol.h"
  8.  
  9. #ifdef IBMPC
  10. #include <windows.h>
  11. #include <malloc.h>
  12. #endif
  13. #ifdef APPLEMAC
  14. #include <Types.h>
  15. #include <Errors.h>
  16. #ifdef __CONDITIONALMACROS__
  17. #include <Printing.h>
  18. #else
  19. #include <PrintTraps.h>
  20. #endif
  21. #endif
  22. #ifndef sun386
  23. #include <stdlib.h>
  24. #endif
  25.  
  26.  
  27. #include <stdio.h>
  28. #include <ctype.h>
  29. #include <math.h>
  30.  
  31. #include "script.h"
  32. #include "molecule.h"
  33. #include "command.h"
  34. #include "abstree.h"
  35. #include "transfor.h"
  36. #include "render.h"
  37. #include "repres.h"
  38. #include "graphics.h"
  39. #include "pixutils.h"
  40.  
  41. #ifdef INVERT
  42. #define InvertY(y) (y)
  43. #else
  44. #define InvertY(y) (-(y))
  45. #endif
  46.  
  47. #define Round(x)       ((int)(x))
  48. #define DatWirFlag  (Long)0x10000
  49. #define DatDasFlag  (Long)0x20000
  50. #define DatCylFlag  (Long)0x40000
  51.  
  52. /* Special thanks to Profs Jane and David Richardson
  53.  * for the following Kinemage colour lookup table */
  54.  
  55. #define MAXMAGECOL 20
  56. static struct {
  57.         int r, g, b;
  58.         char *name;
  59.         } KinemageCol[MAXMAGECOL] = {
  60.     { 255,   0,   0, "red"        },  /*  1 */
  61.     {  23, 256,   0, "green"      },  /*  2 */
  62.     {  62,  62, 255, "blue"       },  /*  3 */
  63.     {   0, 242, 226, "cyan"       },  /*  4 */
  64.     { 255, 246,   0, "yellow"     },  /*  5 */
  65.     { 255,   0, 234, "magenta"    },  /*  6 */
  66.     { 255, 255, 255, "white"      },  /*  7 */
  67.     { 255, 101, 117, "pink"       },  /*  8 */
  68.     { 255,  93,   0, "orange"     },  /*  9 */
  69.     { 140,  54, 255, "purple"     },  /* 10 */
  70.     {  58, 144, 255, "skyblue"    },  /* 11 */
  71.     { 175, 117,  89, "brown"      },  /* 12 */
  72.     { 125, 125, 125, "gray"       },  /* 13 */
  73.     { 255, 156,   0, "gold"       },  /* 15 */
  74.     { 246, 246, 117, "yellowtint" },  /* 16 */
  75.     {   0, 250, 109, "seagreen"   },  /* 17 */
  76.     { 255, 171, 187, "pinktint"   },  /* 18 */
  77.     { 175, 214, 255, "bluetint"   },  /* 19 */
  78.     { 152, 255, 179, "greentint"  },  /* 20 */
  79.     { 255,   0, 101, "hotpink"    }   /* 21 */
  80.         };
  81.  
  82.  
  83. typedef struct {
  84.         Long datum;
  85.         Long count;
  86.     } FreqEntry;
  87.  
  88. #define FREQSIZE  8
  89. static FreqEntry Freq[FREQSIZE];
  90.  
  91.  
  92. static Atom __far *MagePrev;
  93. static char *MageCol;
  94. static FILE *OutFile;
  95. static int SelectAll;
  96.  
  97. /* Macros for commonly used loops */
  98. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  99.                      for(group=chain->glist;group;group=group->gnext)    \
  100.                      for(aptr=group->alist;aptr;aptr=aptr->anext)
  101. #define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext)
  102. #define ForEachBack  for(chain=Database->clist;chain;chain=chain->cnext) \
  103.                      for(bptr=chain->blist;bptr;bptr=bptr->bnext)
  104.  
  105.  
  106. static void FatalScriptError( ptr )
  107.     char *ptr;
  108. {
  109.     if( CommandActive ) WriteChar('\n');
  110.     WriteString("Script Error: Unable to create file `");
  111.     WriteString( ptr );  WriteString("'!\n");
  112.     CommandActive = False;
  113. }
  114.  
  115.  
  116. #ifdef FUNCPROTO
  117. static void IncFreqTable( Long );
  118. static Long GetBondDatum( Bond __far* );
  119. static Long GetHBondDatum( HBond __far* );
  120. #endif
  121.  
  122. static void ResetFreqTable()
  123. {
  124.     register int i;
  125.  
  126.     for( i=0; i<FREQSIZE; i++ )
  127.         Freq[i].count = 0;
  128. }
  129.  
  130. static void IncFreqTable( datum )
  131.     Long datum;
  132. {
  133.     register Long count;
  134.     register int i;
  135.  
  136.     for( i=0; i<FREQSIZE; i++ )
  137.         if( !Freq[i].count )
  138.         {   Freq[i].datum = datum;
  139.             Freq[i].count = 1;
  140.             return;
  141.         } else if( Freq[i].datum == datum )
  142.         {   count = Freq[i].count+1;
  143.             while( i && (Freq[i-1].count<=count) )
  144.             {   Freq[i] = Freq[i-1];  
  145.                 i--;
  146.             }
  147.             Freq[i].datum = datum;
  148.             Freq[i].count = count;
  149.             return;
  150.         }
  151.  
  152.     /* Replace Singletons! */
  153.     if( Freq[FREQSIZE-1].count == 1 )
  154.         Freq[FREQSIZE-1].datum = datum;
  155. }
  156.  
  157.  
  158. static Long GetBondDatum( bptr )
  159.     Bond __far *bptr;
  160. {
  161.     if( bptr->flag & CylinderFlag )
  162.     {   return( DatCylFlag | bptr->radius );
  163.     } else if( bptr->flag & WireFlag )
  164.     {   return( DatWirFlag );
  165.     } else if( bptr->flag & DashFlag )
  166.     {   return( DatDasFlag );
  167.     } else return( (Long)0 );
  168. }
  169.  
  170. static Long GetHBondDatum( bptr )
  171.     HBond __far *bptr;
  172. {
  173.     if( bptr->flag & CylinderFlag )
  174.     {   return( DatCylFlag | bptr->radius );
  175.     } else if( bptr->flag & WireFlag )
  176.     {   return( DatWirFlag );
  177.     } else return( (Long)0 );
  178. }
  179.  
  180.  
  181. #ifndef SCRIPT
  182. #ifdef FUNCPROTO
  183. static void WriteMolScriptAtomSel( Chain __far*, Group __far*, Atom __far* );
  184. #endif
  185.  
  186. static void WriteMolScriptColour( r, g, b )
  187.     int r, g, b;
  188. {
  189.     fprintf(OutFile," rgb %#g %#g %#g",r/255.0,g/255.0,b/255.0);
  190. }
  191.  
  192. static void WriteMolScriptAtomSel( chain, group, aptr )
  193.     Chain __far *chain;
  194.     Group __far *group;
  195.     Atom __far *aptr;
  196. {
  197.     register char *ptr;
  198.     register int i;
  199.  
  200.     fputs("require atom ",OutFile);
  201.     ptr = ElemDesc[aptr->refno];
  202.     for( i=0; i<4; i++ )
  203.         if( ptr[i]=='*' )
  204.         {   fputc('\'',OutFile);
  205.         } else if( ptr[i]!=' ' )
  206.             fputc(ptr[i],OutFile);
  207.  
  208.     fputs(" and in residue ",OutFile);
  209.     if( chain->ident!=' ' && !isdigit(chain->ident) )
  210.         fputc(chain->ident,OutFile);
  211.     fprintf(OutFile,"%d",group->serno);
  212. }
  213.  
  214. static void WriteMolScriptAtoms()
  215. {
  216.     register Chain __far *chain;
  217.     register Group __far *group;
  218.     register Atom __far *aptr;
  219.     register ShadeDesc *shade;
  220.     register Label *label;
  221.     register char *ptr;
  222.  
  223.     char buffer[80];
  224.  
  225.  
  226.     ForEachAtom
  227.     {   if( aptr->flag & SphereFlag )
  228.         {   /* Atom Colour */
  229.             fputs("set atomcolour ",OutFile);
  230.             WriteMolScriptAtomSel(chain,group,aptr);
  231.             shade = Shade + Colour2Shade(aptr->col);
  232.             WriteMolScriptColour(shade->r,shade->g,shade->b);
  233.             fputs(";\n",OutFile);
  234.  
  235.             /* CPK Sphere */
  236.             fputs("set atomradius ",OutFile);
  237.             WriteMolScriptAtomSel(chain,group,aptr);
  238.             fprintf(OutFile," %#g;\ncpk ",aptr->radius/250.0);
  239.             WriteMolScriptAtomSel(chain,group,aptr);
  240.             fputs(";\n",OutFile);
  241.         }
  242.  
  243.         if( aptr->label )
  244.         {   /* Atom Label */
  245.             label = (Label*)aptr->label;
  246.             FormatLabel(chain,group,aptr,label->label,buffer);
  247.  
  248.             fputs("label ",OutFile);
  249.             WriteMolScriptAtomSel(chain,group,aptr);
  250.             fputs(" \"",OutFile);
  251.             for( ptr=buffer; *ptr; ptr++ )
  252.                 if( *ptr!='%' ) fputc(*ptr,OutFile);
  253.             fputs("\";\n",OutFile);
  254.         }
  255.     }
  256. }
  257. #endif
  258.  
  259. static void MolScriptSegment( ptr, src, dst, chain )
  260.     char *ptr;  int src, dst;  char chain;
  261. {   
  262.     if( (chain!=' ') && !isdigit(chain) ) 
  263.     {   fprintf(OutFile,"  %s from %c%d to %c%d;\n",ptr,chain,src,chain,dst);
  264.     } else fprintf(OutFile,"  %s from %d to %d;\n",ptr,src,dst);
  265. }
  266.  
  267.  
  268. int WriteMolScriptFile( name )
  269.     char *name;
  270. {
  271.     register Real temp;
  272.     register Real psi, phi, theta;
  273.     register Chain __far *chain;
  274.     register Group __far *group;
  275.     register Group __far *next;
  276.     register Group __far *prev;
  277.     register int flag,len;
  278.     register char *ptr;
  279.  
  280.     if( !Database )
  281.         return(False);
  282.  
  283.     OutFile = fopen(name,"w");
  284.     if( !OutFile )
  285.     {   FatalScriptError(name);
  286.         return(False);
  287.     }
  288.     fprintf(OutFile,"! File: %s\n",name);
  289.     fputs("! Creator: RasMol Version 2.6\n",OutFile);
  290.     fputs("! Version: MolScript v1.3\n\n",OutFile);
  291.  
  292.     fputs("plot\n",OutFile);
  293.     if( BackR || BackG || BackB )
  294.     {   fputs("  background rgb ",OutFile);
  295.         fprintf(OutFile,"%#g ",  BackR/255.0);
  296.         fprintf(OutFile,"%#g ",  BackG/255.0);
  297.         fprintf(OutFile,"%#g;\n",BackB/255.0);
  298.     }
  299.     temp = 0.004/Scale;
  300.     fprintf(OutFile,"  window %g;\n",temp*Range);
  301.     if( UseSlabPlane )
  302.         fprintf(OutFile,"  slab %g;\n",SideLen/250.0);
  303.     fputc('\n',OutFile);
  304.  
  305.     fprintf(OutFile,"  read mol \"%s\";\n",InfoFileName);
  306.     fputs("  transform atom *\n",OutFile);
  307.     fputs("    by centre position atom *\n",OutFile);
  308.     fputs("    by rotation x 180.0",OutFile);
  309.  
  310.     phi = Rad2Deg*asin(RotX[2]);
  311.     if( (int)phi == 90 )
  312.     {   theta = -Rad2Deg*atan2(RotY[0],RotY[1]);
  313.         psi = 0;
  314.     } else if( (int)phi == -90 )
  315.     {   theta = Rad2Deg*atan2(RotY[0],RotY[1]);
  316.         psi = 0;
  317.     } else /* General Case! */
  318.     {   theta = Rad2Deg*atan2(RotY[2],RotZ[2]);
  319.         psi =  -Rad2Deg*atan2(RotX[1],RotX[0]);
  320.     }
  321.  
  322.     if( (int)psi )   fprintf(OutFile,"\n    by rotation z %#g",InvertY(psi));
  323.     if( (int)phi )   fprintf(OutFile,"\n    by rotation y %#g",phi);
  324.     if( (int)theta ) fprintf(OutFile,"\n    by rotation x %#g",InvertY(-theta));
  325.  
  326.     if( UseSlabPlane || (XOffset!=WRange) || (YOffset!=HRange) )
  327.     {   fputs("\n    by translation ",OutFile);
  328.         fprintf(OutFile,"%#g ",(XOffset-WRange)*temp);
  329.         fprintf(OutFile,"%#g ",-(YOffset-HRange)*temp);
  330.         if( UseSlabPlane )
  331.         {   temp = (1.0-DialValue[7])/500.0;
  332.             fprintf(OutFile,"%#g",SideLen*temp);
  333.         } else fputs("0.0",OutFile);
  334.     }
  335.     fputs(";\n\n",OutFile);
  336.  
  337.     /* fputs("  trace amino-acids;\n",OutFile); */
  338.  
  339.     if( Database->clist )
  340.     {   if( InfoHelixCount<0 )
  341.             DetermineStructure( False );
  342.  
  343.         for( chain=Database->clist; chain; chain=chain->cnext )
  344.         {   prev = (Group __far*)0;
  345.             for( group=chain->glist; group && group->gnext; group=next )
  346.             {   next = group->gnext;
  347.                 if( next->serno < group->serno )
  348.                 {   if( prev && prev!=group )
  349.                         MolScriptSegment("coil",prev->serno,group->serno,
  350.                                                 chain->ident);
  351.                     prev = (Group __far*)0;
  352.                     continue;
  353.                 }
  354.                 flag = group->struc & next->struc;
  355.  
  356.                 if( flag&HelixFlag )
  357.                 {   flag = HelixFlag;
  358.                     ptr = "helix";
  359.                 } else if( flag&SheetFlag )
  360.                 {   flag = SheetFlag;
  361.                     ptr = "strand";
  362.                 } else 
  363.                 {   if( flag&TurnFlag )
  364.                     {   fputs("  turn residue ",OutFile);
  365.                         if( chain->ident != ' ' )
  366.                             fputc(chain->ident,OutFile);
  367.                         fprintf(OutFile,"%d;\n",group->serno);
  368.                     }
  369.                     if( !prev ) prev = group;
  370.                     continue;
  371.                 }
  372.  
  373.                 len = 2;  /* Determine Structure Length */
  374.                 while( next->gnext && (next->gnext->struc&flag)
  375.                            && (next->serno<=next->gnext->serno) )
  376.                 {   next = next->gnext;
  377.                     len++;
  378.                 }
  379.  
  380.                 if( len>2 )
  381.                 {   if( prev && prev!=group ) /* MolScript coil or turn? */
  382.                        MolScriptSegment("coil",prev->serno,group->serno,
  383.                                               chain->ident);
  384.                     MolScriptSegment(ptr,group->serno,next->serno,
  385.                                          chain->ident);
  386.                 prev = next;
  387.                 } 
  388.             }
  389.  
  390.             if( prev && prev!=group )  /* C-terminal coil/turn */
  391.                 MolScriptSegment("coil",prev->serno,group->serno,chain->ident);
  392.         }
  393.     }
  394.  
  395. #ifndef SCRIPT
  396.     WriteMolScriptAtoms();
  397. #endif
  398.  
  399.     fputs("end_plot\n",OutFile);
  400.     fclose(OutFile);
  401. #ifdef APPLEMAC
  402.     SetFileInfo(name,'ttxt','TEXT',133);
  403. #endif
  404.     return( True );
  405. }
  406.  
  407.  
  408.  
  409.  
  410. #ifdef FUNCPROTO
  411. static void WriteScriptDatum( char*, Long );
  412. static void WriteScriptSelectBond( Atom __far*, Atom __far* );
  413. static void WriteScriptHBonds( char*, HBond __far* );
  414. #endif
  415.  
  416.  
  417. static void WriteScriptAll()
  418. {
  419.     if( !SelectAll )
  420.     {   fputs("select all\n",OutFile);
  421.         SelectAll = True;
  422.     }
  423. }
  424.  
  425. static void WriteScriptColour( ptr, col )
  426.     char *ptr;  int col;
  427. {
  428.     register ShadeDesc *shade;
  429.     
  430.     if( col )
  431.     {   shade = Shade + Colour2Shade(col);
  432.         fprintf(OutFile,"colour %s [%d,%d,%d]\n",ptr,
  433.                 shade->r,shade->g,shade->b);
  434.     } else fprintf(OutFile,"colour %s none\n",ptr);
  435. }
  436.  
  437.  
  438. static void WriteScriptBetween( lo, hi )
  439.     int lo, hi;
  440. {
  441.     if( lo != hi )
  442.     {   fprintf(OutFile,"select (atomno>=%d) and (atomno<=%d)\n",lo,hi);
  443.     } else fprintf(OutFile,"select atomno=%d\n",lo);
  444.     SelectAll = False;
  445. }
  446.  
  447. static void WriteScriptSelectBond( src, dst )
  448.     Atom __far *src, __far *dst;
  449. {
  450.     fprintf(OutFile,"select (atomno=%d) or (atomno==%d)\n",
  451.                     src->serno, dst->serno);
  452.     SelectAll = False;
  453. }
  454.  
  455.  
  456. static void WriteScriptAtoms()
  457. {
  458.     register Chain __far *chain;
  459.     register Group __far *group;
  460.     register Atom __far *aptr;
  461.     register int first,last;
  462.     register int same,init;
  463.     register int cpk,vdw;
  464.     register int col,rad;
  465.  
  466.     fputs("\n# Atoms\n",OutFile);
  467.  
  468.     same = True;
  469.     init = False;
  470.     ForEachAtom
  471.         if( !init )
  472.         {   first = last = aptr->serno;
  473.             cpk = IsCPKColour( aptr );
  474.             col = aptr->col;
  475.             init = True;
  476.         } else if( cpk && IsCPKColour(aptr) )
  477.         {   last = aptr->serno;
  478.             if( aptr->col != col )
  479.                 col = 0;
  480.         } else if( aptr->col == col )
  481.         {   last = aptr->serno;
  482.             cpk = False;
  483.         } else if( aptr->col != col )
  484.         {   WriteScriptBetween( first, last );
  485.             if( !col )
  486.             {   fputs("colour atoms cpk\n",OutFile);
  487.             } else WriteScriptColour("atoms",col);
  488.                 
  489.             first = last = aptr->serno;
  490.             cpk = IsCPKColour( aptr );
  491.             col = aptr->col;
  492.             same = False;
  493.         } else last = aptr->serno; 
  494.         
  495.     if( init )
  496.     {   if( !same )
  497.         {   WriteScriptBetween(first,last);
  498.         } else WriteScriptAll();
  499.  
  500.         if( !col )
  501.         {   fputs("colour atoms cpk\n",OutFile);
  502.         } else WriteScriptColour("atoms",col);
  503.     }
  504.  
  505.     if( DrawAtoms )
  506.     {   same = True;
  507.         init = False;
  508.         ForEachAtom
  509.             if( !init )
  510.             {   rad = aptr->flag&SphereFlag? aptr->radius : 0;
  511.                 first = last = aptr->serno;
  512.                 vdw = IsVDWRadius( aptr );
  513.                 init = True;
  514.             } else if( rad == ((aptr->flag&SphereFlag)? aptr->radius : 0) )
  515.             {   if( vdw ) vdw = IsVDWRadius( aptr );
  516.                 last = aptr->serno;
  517.             } else if( vdw && IsVDWRadius(aptr) )
  518.             {   last = aptr->serno;
  519.                 rad = -1;
  520.             } else 
  521.             {   WriteScriptBetween(first,last);
  522.                 if( rad == -1 )
  523.                 {   fputs("spacefill on\n",OutFile);
  524.                 } else if( rad )
  525.                 {   fprintf(OutFile,"spacefill %d\n",rad);
  526.                 } else fputs("spacefill off\n",OutFile); 
  527.  
  528.                 rad = aptr->flag&SphereFlag? aptr->radius : 0;
  529.                 first = last = aptr->serno;
  530.                 vdw = IsVDWRadius( aptr );
  531.                 same = False;
  532.             }
  533.  
  534.         if( !same )
  535.         {   WriteScriptBetween(first,last);
  536.         } else WriteScriptAll();
  537.  
  538.         if( rad == -1 )
  539.         {   fputs("spacefill on\n",OutFile);
  540.         } else if( rad )
  541.         {   fprintf(OutFile,"spacefill %d\n",rad);
  542.         } else fputs("spacefill off\n",OutFile); 
  543.  
  544.         if( UseShadow )
  545.         {   fputs("set shadow on\n",OutFile);
  546.         } else fputs("set shadow off\n",OutFile);
  547.  
  548.     } else
  549.     {   WriteScriptAll();
  550.         fputs("spacefill off\n",OutFile);
  551.     }
  552.         
  553. }
  554.  
  555.  
  556. static void WriteScriptDatum( ptr, datum )
  557.     char *ptr;  Long datum;
  558. {
  559.     if( datum & DatCylFlag )
  560.     {   fprintf(OutFile,"%s %d\n",ptr,(int)(datum-DatCylFlag));
  561.     } else if( datum & DatWirFlag )
  562.     {   fprintf(OutFile,"%s on\n",ptr);
  563.     } else if( datum & DatDasFlag )
  564.     {   fprintf(OutFile,"%s dash\n",ptr);
  565.     } else fprintf(OutFile,"%s off\n",ptr);
  566. }
  567.  
  568.  
  569. static void WriteScriptBonds()
  570. {
  571.     register Bond __far *bptr;
  572.     register Long defdat;
  573.     register Long datum;
  574.     register int col;
  575.  
  576.     fputs("\n# Bonds\n",OutFile);
  577.  
  578.     ResetFreqTable();
  579.     ForEachBond
  580.         IncFreqTable(GetBondDatum(bptr));
  581.  
  582.     WriteScriptAll();
  583.     defdat = Freq[0].datum;
  584.     WriteScriptDatum("wireframe",defdat);
  585.  
  586.     if( Freq[1].count )
  587.     {   ForEachBond
  588.         {   datum = GetBondDatum(bptr);
  589.             if( datum != defdat )
  590.             {    WriteScriptSelectBond(bptr->srcatom,bptr->dstatom);
  591.                  WriteScriptDatum("wireframe",datum);
  592.             }
  593.         }
  594.     } else if( !defdat )
  595.         return;
  596.  
  597.     ResetFreqTable();
  598.     ForEachBond
  599.         IncFreqTable(bptr->col);
  600.  
  601.     col = (int)Freq[0].datum;
  602.     if( col )
  603.     {   WriteScriptAll();
  604.         WriteScriptColour("bonds",col);
  605.     }
  606.  
  607.     if( Freq[1].count )
  608.         ForEachBond
  609.             if( bptr->col != col )
  610.             {   WriteScriptSelectBond(bptr->srcatom,bptr->dstatom);
  611.                 WriteScriptColour("bonds",bptr->col);
  612.             }
  613. }
  614.  
  615. static void WriteScriptBackbone()
  616. {
  617.     register Chain __far *chain;
  618.     register Bond __far *bptr;
  619.  
  620.     register Long defdat;
  621.     register Long datum;
  622.     register int col;
  623.  
  624.     fputs("\n# Backbone\n",OutFile);
  625.  
  626.     ResetFreqTable();
  627.     ForEachBack
  628.         IncFreqTable(GetBondDatum(bptr));
  629.  
  630.     WriteScriptAll();
  631.     defdat = Freq[0].datum;
  632.     WriteScriptDatum("backbone",defdat);
  633.  
  634.     if( Freq[1].count )
  635.     {   ForEachBack
  636.         {   datum = GetBondDatum(bptr);
  637.             if( datum != defdat )
  638.             {    WriteScriptSelectBond(bptr->srcatom,bptr->dstatom);
  639.                  WriteScriptDatum("backbone",datum);
  640.             }
  641.         }
  642.     } else if( !defdat )
  643.         return;
  644.  
  645.     ResetFreqTable();
  646.     ForEachBack
  647.         IncFreqTable(bptr->col);
  648.  
  649.     col = (int)Freq[0].datum;
  650.     if( col )
  651.     {   WriteScriptAll();
  652.         WriteScriptColour("backbone",col);
  653.     }
  654.  
  655.     if( Freq[1].count )
  656.         ForEachBack
  657.             if( bptr->col != col )
  658.             {   WriteScriptSelectBond(bptr->srcatom,bptr->dstatom);
  659.                 WriteScriptColour("backbone",bptr->col);
  660.             }
  661. }
  662.  
  663. static void WriteScriptRibbons()
  664. {
  665.     register Chain __far *chain;
  666.     register Group __far *group;
  667.     register Atom __far *aptr;
  668.  
  669.     fputs("\n# Ribbons\n",OutFile);
  670.  
  671.     if( DrawRibbon )
  672.     {   fprintf(OutFile,"set strands %d\n",SplineCount);
  673.         fprintf(OutFile,"set cartoon %s\n",DrawBetaArrows?"on":"off");
  674.         fprintf(OutFile,"set cartoon %d\n",CartoonHeight);
  675.  
  676.         for( chain=Database->clist; chain; chain=chain->cnext )
  677.             for( group=chain->glist; group; group=group->gnext )
  678.             {    if( IsAmino(group->refno) )
  679.                  {   aptr = FindGroupAtom(group,1);
  680.                  } else aptr = FindGroupAtom(group,7);
  681.                  if( !aptr ) continue;
  682.  
  683.                  fprintf(OutFile,"select atomno=%d\n",aptr->serno);
  684.                  SelectAll = False;
  685.  
  686.                  if( group->flag & RibbonFlag )
  687.                  {   fprintf(OutFile,"ribbons %d\n",group->width);
  688.                  } else if( group->flag & CartoonFlag )
  689.                  {   fprintf(OutFile,"cartoon %d\n",group->width);
  690.                  } else if( group->flag & StrandFlag )
  691.                  {   fprintf(OutFile,"strands %d\n",group->width);
  692.                  } else if( group->flag & DashStrandFlag )
  693.                  {   fprintf(OutFile,"strands dash %d\n",group->width);
  694.                  } else if( group->flag & TraceFlag )
  695.                  {   fprintf(OutFile,"trace %d\n",group->width);
  696.                  } else fputs("ribbons off\n",OutFile);
  697.  
  698.                  if( group->col1 != group->col2 )
  699.                  {   WriteScriptColour("ribbon1",group->col1);
  700.                      WriteScriptColour("ribbon2",group->col2);
  701.                  } else WriteScriptColour("ribbons",group->col1);
  702.             }
  703.     } else
  704.     {   WriteScriptAll();
  705.         fputs("ribbons off\n",OutFile);
  706.     }
  707. }
  708.  
  709.  
  710. static void WriteScriptHBonds( obj, list )
  711.     char *obj;  HBond __far *list;
  712. {
  713.     register HBond __far *ptr;
  714.     register Long defdat;
  715.     register Long datum;
  716.     register int col;
  717.  
  718.     ResetFreqTable();
  719.     for( ptr=list; ptr; ptr=ptr->hnext )
  720.         IncFreqTable(GetHBondDatum(ptr));
  721.  
  722.     WriteScriptAll();
  723.     defdat = Freq[0].datum;
  724.     WriteScriptDatum(obj,defdat);
  725.  
  726.     if( Freq[1].count )
  727.     {   for( ptr=list; ptr; ptr=ptr->hnext )
  728.         {   datum = GetHBondDatum(ptr);
  729.             if( datum != defdat )
  730.             {    WriteScriptSelectBond(ptr->src,ptr->dst);
  731.                  WriteScriptDatum(obj,datum);
  732.             }
  733.         }
  734.     } else if( !defdat )
  735.         return;
  736.  
  737.     ResetFreqTable();
  738.     for( ptr=list; ptr; ptr=ptr->hnext )
  739.         IncFreqTable(ptr->col);
  740.  
  741.     col = (int)Freq[0].datum;
  742.     if( col )
  743.     {   WriteScriptAll();
  744.         WriteScriptColour(obj,col);
  745.     }
  746.  
  747.     if( Freq[1].count )
  748.         for( ptr=list; ptr; ptr=ptr->hnext )
  749.             if( ptr->col != col )
  750.             {   WriteScriptSelectBond(ptr->src,ptr->dst);
  751.                 WriteScriptColour(obj,ptr->col);
  752.             }
  753. }
  754.  
  755. static void WriteScriptLabels()
  756. {
  757.     register Chain __far *chain;
  758.     register Group __far *group;
  759.     register Atom __far *aptr;
  760.     register int first,last;
  761.     register Label *label;
  762.  
  763.     fputs("\n# Labels\n",OutFile);
  764.     WriteScriptAll();
  765.     fputs("labels off\n",OutFile);
  766.     if( !DrawLabels ) return;
  767.  
  768.     if( UseLabelCol )
  769.     {   fprintf(OutFile,"colour labels [%d,%d,%d]\n",LabR,LabG,LabB);
  770.     } else fputs("colour labels none\n",OutFile);
  771.     fprintf(OutFile,"set fontsize %d\n",FontSize);
  772.  
  773.     label = (Label*)0;
  774.     ForEachAtom
  775.         if( aptr->label != label )
  776.         {   if( label )
  777.             {   WriteScriptBetween(first,last);
  778.                 fprintf(OutFile,"label \"%s\"\n",label->label);
  779.             }
  780.             label = (Label*)aptr->label;
  781.             first = last = aptr->serno;
  782.         } else last = aptr->serno;
  783.  
  784.     if( label )
  785.     {   WriteScriptBetween(first,last);
  786.         fprintf(OutFile,"label \"%s\"",label->label);
  787.     }
  788. }
  789.  
  790.  
  791. static void WriteScriptMonitors()
  792. {
  793.     register Monitor *ptr;
  794.     register int col;
  795.  
  796.     fputs("\n# Monitors\n",OutFile);
  797.     if( !MonitList )
  798.     {   fputs("monitors off\n",OutFile);
  799.         return;
  800.     }
  801.  
  802.     fprintf(OutFile,"set monitors %s\n",DrawMonitDistance?"on":"off");
  803.  
  804.     ResetFreqTable();
  805.     for( ptr=MonitList; ptr; ptr=ptr->next )
  806.     {   fprintf(OutFile,"monitor %d %d\n",ptr->src->serno,ptr->dst->serno);
  807.         IncFreqTable(ptr->col);
  808.     }
  809.  
  810.     col = (int)Freq[0].datum;
  811.     if( col )
  812.     {   WriteScriptAll();
  813.         WriteScriptColour("monitors",col);
  814.     }
  815.  
  816.     if( Freq[1].count )
  817.         for( ptr=MonitList; ptr; ptr=ptr->next )
  818.             if( ptr->col != col )
  819.             {   WriteScriptSelectBond(ptr->src,ptr->dst);
  820.                 WriteScriptColour("monitor",ptr->col);
  821.             }
  822. }
  823.  
  824.  
  825. int WriteScriptFile( name )
  826.     char *name;
  827. {
  828.     register int theta,phi,psi;
  829.     register char *ptr;
  830.     register int temp;
  831.  
  832.     OutFile = fopen(name,"w");
  833.     if( !OutFile )
  834.     {   FatalScriptError(name);
  835.         return(False);
  836.     }
  837.  
  838.     fprintf(OutFile,"#!rasmol -script\n# File: %s\n",name);
  839.     fputs("# Creator: RasMol Version 2.6\n\n",OutFile);
  840.     fprintf(OutFile,"background [%d,%d,%d]\n",BackR,BackG,BackB);
  841.     fputs("zap\n",OutFile);
  842.  
  843.     if( !Database )
  844.     {   /* No Molecule! */
  845.         fclose(OutFile);
  846. #ifdef APPLEMAC
  847.         SetFileInfo(name,'RSML','RSML',133);
  848. #endif
  849.         return(True);
  850.     }
  851.  
  852.     /* Molecule File Name */
  853.     switch( DataFileFormat )
  854.     {   default:
  855.         case(FormatPDB):      ptr = "pdb";      break;
  856.         case(FormatAlchemy):  ptr = "alchemy";  break;
  857.         case(FormatCharmm):   ptr = "charmm";   break;
  858.         case(FormatMol2):     ptr = "mol2";     break;
  859.         case(FormatMDL):      ptr = "mdl";      break;
  860.         case(FormatXYZ):      ptr = "xyz";      break;
  861.     }
  862.     fprintf(OutFile,"load %s \"%s\"\n",ptr,InfoFileName);
  863.  
  864.     /* Colour Details */
  865.     fprintf(OutFile,"set ambient %d\n", (int)(100*Ambient) );
  866.     fputs("set specular ",OutFile);
  867.     if( FakeSpecular )
  868.     {   fprintf(OutFile,"on\nset specpower %d\n",SpecPower);
  869.     } else fputs("off\n",OutFile);
  870.     putc('\n',OutFile);
  871.  
  872.     /* Transformation */
  873.     fputs("reset\n",OutFile);
  874.     if( UseSlabPlane )
  875.     {   temp = (int)(50.0*DialValue[7]);
  876.         if( temp )
  877.         {   fprintf(OutFile,"slab %d\n",temp+50);
  878.         } else fputs("slab on\n",OutFile);
  879.  
  880.         fputs("set slabmode ",OutFile);
  881.         switch( SlabMode )
  882.         {   default:            
  883.             case(SlabClose):    ptr = "solid";    break;
  884.             case(SlabReject):   ptr = "reject";   break;
  885.             case(SlabHalf):     ptr = "half";     break;
  886.             case(SlabHollow):   ptr = "hollow";   break;
  887.             case(SlabSection):  ptr = "section";
  888.         }
  889.         fputs(ptr,OutFile);
  890.         putc('\n',OutFile);
  891.     } else fputs("slab off\n",OutFile);
  892.  
  893.     phi = Round(Rad2Deg*asin(RotX[2]));
  894.     if( phi == 90 )
  895.     {   theta = -Round(Rad2Deg*atan2(RotY[0],RotY[1]));
  896.         psi = 0;
  897.     } else if( phi == -90 )
  898.     {   theta = Round(Rad2Deg*atan2(RotY[0],RotY[1]));
  899.         psi = 0;
  900.     } else /* General Case! */
  901.     {   theta = Round(Rad2Deg*atan2(RotY[2],RotZ[2]));
  902.         psi =  Round(-Rad2Deg*atan2(RotX[1],RotX[0]));
  903.     }
  904.  
  905.     if( psi )   fprintf(OutFile,"rotate z %d\n",InvertY(-psi));
  906.     if( phi )   fprintf(OutFile,"rotate y %d\n",phi);
  907.     if( theta ) fprintf(OutFile,"rotate x %d\n",InvertY(-theta));
  908.  
  909.     temp = (int)(100.0*DialValue[4]);
  910.     if( temp ) fprintf(OutFile,"translate x %d\n",temp);
  911.     temp = (int)(100.0*DialValue[5]);
  912.     if( temp ) fprintf(OutFile,"translate y %d\n",InvertY(-temp));
  913.  
  914.     if( DialValue[3] != 0.0 )
  915.     {   if( DialValue[3]<0.0 )
  916.         {   temp = (int)(100*DialValue[3]);
  917.         } else temp = (int)(100*MaxZoom*DialValue[3]);
  918.         fprintf(OutFile,"zoom %d\n",temp+100);
  919.     }
  920.     putc('\n',OutFile);
  921.  
  922.     /* Rendering */
  923.     if( DrawAxes || DrawBoundBox || DrawUnitCell )
  924.         fprintf(OutFile,"colour axes [%d %d %d]\n",BoxR,BoxG,BoxB);
  925.     if( DrawBonds )
  926.         fprintf(OutFile,"set bonds %s\n", DrawDoubleBonds? "on":"off" );
  927.  
  928.     fprintf(OutFile,"set axes %s\n", DrawAxes? "on":"off" );
  929.     fprintf(OutFile,"set boundingbox %s\n", DrawBoundBox? "on":"off" );
  930.     fprintf(OutFile,"set unitcell %s\n", DrawUnitCell? "on":"off" );
  931.  
  932.     if( Database->hlist )
  933.     {   fputs("set hbond ",OutFile);
  934.         fputs(HBondMode?"backbone":"sidechain",OutFile);
  935.         fputc('\n',OutFile);
  936.     }
  937.  
  938.     if( Database->slist )
  939.     {   fputs("set ssbond ",OutFile);
  940.         fputs(SSBondMode?"backbone":"sidechain",OutFile);
  941.         fputc('\n',OutFile);
  942.     }
  943.  
  944.     fputs("set bondmode and\ndots off\n\n",OutFile); 
  945.     fputs("\n# Avoid Colour Problems!\nselect all\n",OutFile);
  946.     fputs("colour bonds none\ncolour backbone none\n",OutFile);
  947.     fputs("colour hbonds none\ncolour ssbonds none\n",OutFile);
  948.     fputs("colour ribbons none\ncolour white\n",OutFile);
  949.     SelectAll = True;
  950.  
  951.     WriteScriptAtoms();
  952.     if( UseSlabPlane && (SlabMode==SlabSection) )
  953.     {   /* Section Mode Slabbing! */
  954.         fclose(OutFile);
  955. #ifdef APPLEMAC
  956.         SetFileInfo(name,'RSML','RSML',133);
  957. #endif
  958.         return(True);
  959.     }
  960.  
  961.     WriteScriptBonds();
  962.     WriteScriptRibbons();
  963.     WriteScriptBackbone();
  964.     WriteScriptLabels();
  965.     WriteScriptMonitors();
  966.     fputc('\n',OutFile);
  967.     
  968.     WriteScriptHBonds("ssbonds",Database->slist);
  969.     WriteScriptHBonds("hbonds",Database->hlist);
  970.     WriteScriptAll();
  971.  
  972.     fclose(OutFile);
  973. #ifdef APPLEMAC
  974.     SetFileInfo(name,'RSML','RSML',133);
  975. #endif
  976.     return( True );
  977. }
  978.  
  979.  
  980.  
  981. #ifdef FUNCPROTO
  982. static int CheckKinemageChain( Atom __far*, Atom __far*, Chain __far* );
  983. static void OutputKinemageVector( Atom __far*, Atom __far*, int );
  984. static void WriteKinemageBonds( Chain __far* );
  985. static void WriteKinemageSpheres( Chain __far* );
  986. static void WriteKinemageRibbons( Chain __far* );
  987. static void WriteKinemageLabels( Chain __far* );
  988. #endif
  989.  
  990.  
  991. static char *FindKinemageCol( r, g, b )
  992.     int r, g, b;
  993. {
  994.     register Long dist,best;
  995.     register int dr,dg,db;
  996.     register int i,res;
  997.  
  998.     res = 0;
  999.     dr = KinemageCol[0].r - r;
  1000.     dg = KinemageCol[0].g - g;
  1001.     db = KinemageCol[0].b - b;
  1002.     best = (Long)dr*dr + (Long)dg*dg + (Long)db*db;
  1003.  
  1004.     for( i=1; i<MAXMAGECOL; i++ )
  1005.     {   dr = KinemageCol[i].r - r;
  1006.         dg = KinemageCol[i].g - g;
  1007.         db = KinemageCol[i].b - b;
  1008.         dist = (Long)dr*dr + (Long)dg*dg + (Long)db*db;  
  1009.  
  1010.         if( dist < best ) 
  1011.         {   best = dist;
  1012.             res = i;
  1013.         }
  1014.     }
  1015.     return( KinemageCol[res].name );
  1016. }
  1017.  
  1018.  
  1019. static char *GetKinemageCol( col )
  1020.     int col;
  1021. {
  1022.     register ShadeDesc *ptr;
  1023.  
  1024.     ptr = Shade + Colour2Shade(col);
  1025.     return( FindKinemageCol(ptr->r,ptr->g,ptr->b) );
  1026. }
  1027.  
  1028.  
  1029. /* Used by CheckKinemageChain! */
  1030. static Group __far *sgrp;
  1031. static Group __far *dgrp;
  1032.  
  1033. static int CheckKinemageChain( src, dst, chain )
  1034.     Atom __far *src, __far *dst;  
  1035.     Chain __far *chain;
  1036. {
  1037.     register Group __far *group;
  1038.     register Atom __far *aptr;
  1039.  
  1040.     /* Determine Chain and Groups */
  1041.     sgrp = dgrp = (Group __far*)0;
  1042.  
  1043.     if( chain )
  1044.     {   for( group=chain->glist; group; group=group->gnext )
  1045.         {   for( aptr=group->alist; aptr; aptr=aptr->anext )
  1046.             {   if( aptr == src ) sgrp = group;
  1047.                 if( aptr == dst ) dgrp = group;
  1048.             }
  1049.             if( sgrp && dgrp ) 
  1050.                 return( True );
  1051.         }
  1052.     } else for( chain=Database->clist; chain; chain=chain->cnext )
  1053.     {   for( group=chain->glist; group; group=group->gnext )
  1054.         {   for( aptr=group->alist; aptr; aptr=aptr->anext )
  1055.             {   if( aptr == src ) sgrp = group;
  1056.                 if( aptr == dst ) dgrp = group;
  1057.             }
  1058.             if( sgrp && dgrp ) 
  1059.                 return( True );
  1060.         }
  1061.     }
  1062.     return( False );
  1063. }
  1064.  
  1065. static void OutputKinemageVector( src, dst, col )
  1066.     Atom __far *src, __far *dst;  
  1067.     int col;
  1068. {
  1069.     register Atom __far *aptr;
  1070.     register Real x, y, z;
  1071.     register char *col1;
  1072.     register char *col2;
  1073.  
  1074.     if( !col )
  1075.     {   col1 = GetKinemageCol(src->col);
  1076.         col2 = GetKinemageCol(dst->col);
  1077.     } else col1 = col2 = GetKinemageCol(col);
  1078.  
  1079.     if( (col1!=MageCol) && (col2==MageCol) )
  1080.     {   aptr = src;  src = dst;  dst = aptr;
  1081.         col2 = col1;  col1 = MageCol;
  1082.     }
  1083.  
  1084.  
  1085.     if( col1 != MageCol )
  1086.     {   fprintf(OutFile,"@vectorlist {} color= %s\n",col1);
  1087.         MagePrev = (Atom __far*)0;
  1088.     }
  1089.  
  1090.     if( src != MagePrev )
  1091.     {   if( MainGroupCount>1 )
  1092.         {   fprintf(OutFile,"{%.4s %.3s %d}", ElemDesc[src->refno], 
  1093.                     Residue[sgrp->refno], sgrp->serno );
  1094.         } else fprintf(OutFile,"{%.4s %d}",ElemDesc[src->refno],src->serno);
  1095.         fprintf(OutFile," P %g %g %g\n", src->xorg/250.0, 
  1096.                 InvertY(src->yorg)/250.0, src->zorg/250.0 );
  1097.     }
  1098.  
  1099.     if( col1 != col2 )
  1100.     {   x = (src->xorg+dst->xorg)/500.0;
  1101.         y = (src->yorg+dst->yorg)/500.0;
  1102.         z = (src->zorg+dst->zorg)/500.0;
  1103.  
  1104.         fprintf(OutFile,"{} L %g %g %g\n", x, InvertY(y), z );
  1105.         fprintf(OutFile,"@vectorlist {} color= %s\n",col2);
  1106.         fprintf(OutFile,"{} P %g %g %g\n", x, InvertY(y), z );
  1107.     }
  1108.  
  1109.     if( MainGroupCount>1 )
  1110.     {   fprintf(OutFile,"{%.4s %.3s %d}", ElemDesc[dst->refno],
  1111.                 Residue[dgrp->refno], dgrp->serno );
  1112.     } else fprintf(OutFile,"{%.4s %d}",ElemDesc[dst->refno],dst->serno);
  1113.     fprintf(OutFile," L %g %g %g\n", dst->xorg/250.0,
  1114.             InvertY(dst->yorg)/250.0, dst->zorg/250.0 );
  1115.  
  1116.     MagePrev = dst;
  1117.     MageCol = col2;
  1118. }
  1119.  
  1120.  
  1121. static void WriteKinemageBonds( chain )
  1122.     Chain __far *chain;
  1123. {
  1124.     register Bond __far *bptr;
  1125.     register Bond __far *flag;
  1126.  
  1127.     MagePrev = (Atom __far*)0;  
  1128.     MageCol = (char*)0;
  1129.  
  1130.     ForEachBond
  1131.         if( KinemageFlag || (bptr->flag&DrawBondFlag) )
  1132.         {   if( CheckKinemageChain(bptr->srcatom,bptr->dstatom,chain) )
  1133.             {   if( !MagePrev ) 
  1134.                     fputs("@subgroup {wireframe} dominant\n",OutFile);
  1135.                 OutputKinemageVector(bptr->srcatom,bptr->dstatom,bptr->col);
  1136.             }
  1137.         }
  1138.  
  1139.     if( !chain->blist ) 
  1140.         return;
  1141.  
  1142.     /* Test for displayed backbone */
  1143.     for( flag=chain->blist; flag; flag=flag->bnext )
  1144.         if( flag->flag & DrawBondFlag ) break;
  1145.     if( !KinemageFlag && !flag ) return;
  1146.  
  1147.     MagePrev = (Atom __far*)0;  
  1148.     MageCol = (char*)0;
  1149.  
  1150.     for( bptr=chain->blist; bptr; bptr=bptr->bnext )
  1151.         if( KinemageFlag || (bptr->flag&DrawBondFlag) )
  1152.         {   if( CheckKinemageChain(bptr->srcatom,bptr->dstatom,chain) )
  1153.             {   if( !MagePrev )
  1154.                 {   fputs("@subgroup {alpha trace} dominant",OutFile);
  1155.                     fputs( (KinemageFlag && !flag)? " off\n":"\n",OutFile);
  1156.                 }
  1157.                 OutputKinemageVector(bptr->srcatom,bptr->dstatom,bptr->col);
  1158.             }
  1159.         }
  1160. }
  1161.  
  1162.  
  1163. static void WriteKinemageSpheres( chain )
  1164.     Chain __far *chain;
  1165. {
  1166.     register Group __far *group;
  1167.     register Atom __far *aptr;
  1168.     register char *col;
  1169.     register int radius;
  1170.  
  1171.     MageCol = (char*)0;
  1172.     for( group=chain->glist; group; group=group->gnext )
  1173.         for( aptr=group->alist; aptr; aptr=aptr->anext )
  1174.             if( aptr->flag & SphereFlag )
  1175.             {   if( !MageCol )
  1176.                     fputs("@subgroup {CPK spheres} dominant\n",OutFile);
  1177.  
  1178.                 col = GetKinemageCol(aptr->col);
  1179.                 if( (col!=MageCol) || (aptr->radius!=radius) )
  1180.                 {   fprintf(OutFile,"@balllist {} color= %s radius= %g\n",
  1181.                                     col, aptr->radius/250.0);
  1182.                     radius = aptr->radius;
  1183.                     MageCol = col;
  1184.                 }
  1185.  
  1186.                 if( MainGroupCount>1 )
  1187.                 {   fprintf(OutFile,"{%.4s %.3s %d}", ElemDesc[aptr->refno],
  1188.                                     Residue[group->refno], group->serno );
  1189.                 } else fprintf(OutFile,"{%.4s %d}",ElemDesc[aptr->refno],
  1190.                                     aptr->serno);
  1191.                 fprintf(OutFile," %g %g %g\n", aptr->xorg/250.0,
  1192.                        InvertY(aptr->yorg)/250.0, aptr->zorg/250.0 );
  1193.             }
  1194. }
  1195.  
  1196.  
  1197. static void WriteKinemageRibbons( chain )
  1198.     Chain __far *chain;
  1199. {
  1200. }
  1201.  
  1202.  
  1203.  
  1204. static void WriteKinemageLabels( chain )
  1205.     Chain __far *chain;
  1206. {
  1207.     register Group __far *group;
  1208.     register Atom __far *aptr;
  1209.     register Label *label;
  1210.     register char *col;
  1211.  
  1212.     auto char buffer[256];
  1213.  
  1214.     MageCol = (char*)0;
  1215.     for( group=chain->glist; group; group=group->gnext )
  1216.         for( aptr=group->alist; aptr; aptr=aptr->anext )
  1217.             if( aptr->label )
  1218.             {   if( !MageCol )
  1219.                     fputs("@subgroup {labels} dominant\n",OutFile);
  1220.                 if( UseLabelCol )
  1221.                 {   col = FindKinemageCol(LabR,LabG,LabB);
  1222.                 } else col = GetKinemageCol(aptr->col);
  1223.  
  1224.                 if( col != MageCol )
  1225.                     fprintf(OutFile,"@labellist {} color= %s\n",col);
  1226.                 label = (Label*)aptr->label;
  1227.                 FormatLabel(chain,group,aptr,label->label,buffer);
  1228.                 fprintf(OutFile,"{%s} %g %g %g\n", buffer, aptr->xorg/250.0, 
  1229.                         InvertY(aptr->yorg)/250.0, aptr->zorg/250.0);
  1230.                 MageCol = col;
  1231.             }
  1232. }
  1233.  
  1234.  
  1235. static void OutputKinemageUnitCell()
  1236. {
  1237. }
  1238.  
  1239.  
  1240. static void WriteKinemageData()
  1241. {
  1242.     register DotStruct __far *ptr;
  1243.     register HBond __far *hptr;
  1244.     register Atom __far *src;
  1245.     register Atom __far *dst;
  1246.     register Real dx, dy, dz;
  1247.     register char *col;
  1248.     register int i;
  1249.  
  1250.     /* Hydrogen Bonds */
  1251.     for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
  1252.         if( hptr->flag & DrawBondFlag ) break;
  1253.  
  1254.     if( KinemageFlag && Database->hlist )
  1255.     {   fputs("@group {h-bonds}",OutFile);
  1256.         fputs( hptr? "\n" : "off", OutFile );
  1257.  
  1258.         fputs("@subgroup {sidechain} dominant",OutFile);
  1259.         fputs( HBondMode? " off\n" : "\n", OutFile);
  1260.         for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
  1261.         {   CheckKinemageChain( hptr->src, hptr->dst, (Chain __far*)0 );
  1262.             OutputKinemageVector( hptr->src, hptr->dst, hptr->col);
  1263.         }
  1264.  
  1265.         fputs("@subgroup {mainchain} dominant",OutFile);
  1266.         fputs( HBondMode? "\n" : " off\n", OutFile);
  1267.         for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
  1268.             if( hptr->srcCA && hptr->dstCA )
  1269.             {   CheckKinemageChain(hptr->srcCA,hptr->dstCA,(Chain __far*)0);
  1270.                 OutputKinemageVector( hptr->srcCA, hptr->dstCA, hptr->col);
  1271.             }
  1272.     } else if( hptr )
  1273.     {   fputs("@group {h-bonds} dominant\n",OutFile);
  1274.         for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
  1275.             if( hptr->flag&DrawBondFlag )
  1276.             {   src = HBondMode? hptr->srcCA : hptr->src;
  1277.                 dst = HBondMode? hptr->dstCA : hptr->dst;
  1278.  
  1279.                 if( src && dst )
  1280.                 {   CheckKinemageChain( src, dst, (Chain __far*)0 );
  1281.                     OutputKinemageVector( src, dst, hptr->col);
  1282.                 }
  1283.             }
  1284.     }
  1285.  
  1286.  
  1287.     /* Disulphide Bridges */
  1288.     for( hptr=Database->slist; hptr; hptr=hptr->hnext )
  1289.         if( hptr->flag & DrawBondFlag ) break;
  1290.  
  1291.     if( KinemageFlag && Database->slist )
  1292.     {   fputs("@group {S-S bridges}",OutFile);
  1293.         fputs( hptr? "\n" : "off", OutFile );
  1294.  
  1295.         fputs("@subgroup {sidechain} dominant",OutFile);
  1296.         fputs( SSBondMode? " off\n" : "\n", OutFile);
  1297.         for( hptr=Database->slist; hptr; hptr=hptr->hnext )
  1298.         {   CheckKinemageChain( hptr->src, hptr->dst, (Chain __far*)0 );
  1299.             OutputKinemageVector(hptr->src,hptr->dst,hptr->col);
  1300.         }
  1301.  
  1302.         fputs("@subgroup {mainchain} dominant",OutFile);
  1303.         fputs( SSBondMode? "\n" : " off\n", OutFile);
  1304.         for( hptr=Database->slist; hptr; hptr=hptr->hnext )
  1305.         {   CheckKinemageChain( hptr->srcCA, hptr->dstCA, (Chain __far*)0 );
  1306.             OutputKinemageVector( hptr->srcCA, hptr->dstCA, hptr->col );
  1307.         }
  1308.     } else if( hptr )
  1309.     {   fputs("@group {S-S bridges} dominant\n",OutFile);
  1310.         for( hptr=Database->slist; hptr; hptr=hptr->hnext )
  1311.             if( hptr->flag&DrawBondFlag )
  1312.             {   CheckKinemageChain( hptr->src, hptr->dst, (Chain __far*)0 );
  1313.                 OutputKinemageVector( SSBondMode?hptr->srcCA:hptr->src,
  1314.                                       SSBondMode?hptr->dstCA:hptr->dst,
  1315.                                       hptr->col );
  1316.             }
  1317.     }
  1318.  
  1319.  
  1320.     /* Dot Surfaces */
  1321.     if( DrawDots )
  1322.     {   fputs("@group {dot surface} dominant\n",OutFile);
  1323.         MageCol = (char*)0;
  1324.  
  1325.         for( ptr=DotPtr; ptr; ptr=ptr->next )
  1326.             for( i=0; i<ptr->count; i++ )
  1327.             {   col = GetKinemageCol(ptr->col[i]);
  1328.                 if( col != MageCol )
  1329.                 {   fprintf(OutFile,"@dotlist {} color= %s\n",col);
  1330.                     MageCol = col;
  1331.                 }
  1332.                 fprintf(OutFile, "{} %g %g %g\n", ptr->xpos[i]/250.0,
  1333.                         InvertY(ptr->ypos[i])/250.0, ptr->zpos[i]/250.0 );
  1334.             }
  1335.     }
  1336.  
  1337.     /* Draw `Background' Objects */
  1338.     if( !KinemageFlag && !DrawAxes && 
  1339.         !DrawBoundBox && !DrawUnitCell )
  1340.         return;
  1341.  
  1342.     dx = MaxX/250.0;  dy = MaxY/250.0;  dz = MaxZ/250.0;
  1343.     MageCol = FindKinemageCol( BoxR, BoxG, BoxB );
  1344.  
  1345.     if( DrawAxes || KinemageFlag )
  1346.     {   fputs("@group {coord axes} dominant",OutFile);
  1347.         fputs( (DrawAxes?"\n":" off\n"), OutFile );
  1348.         fprintf(OutFile,"@vectorlist {} color= %s\n",MageCol);
  1349.  
  1350.         fprintf(OutFile,"{} P %g 0 0\n{} L %g 0 0\n",-dx,dx);
  1351.         fprintf(OutFile,"{} P 0 %g 0\n{} L 0 %g 0\n",-dy,dy);
  1352.         fprintf(OutFile,"{} P 0 0 %g\n{} L 0 0 %g\n",-dz,dz);
  1353.     }
  1354.  
  1355.     if( DrawBoundBox || KinemageFlag )
  1356.     {   fputs("@group {bound box} dominant",OutFile);
  1357.         fputs( (DrawAxes?"\n":" off\n"), OutFile );
  1358.         fprintf(OutFile,"@vectorlist {} color= %s\n",MageCol);
  1359.  
  1360.         fprintf(OutFile,"{} P %g %g %g\n",-dx,-dy,-dz);
  1361.         fprintf(OutFile,"{} L %g %g %g\n", dx,-dy,-dz);
  1362.         fprintf(OutFile,"{} L %g %g %g\n", dx, dy,-dz);
  1363.         fprintf(OutFile,"{} L %g %g %g\n",-dx, dy,-dz);
  1364.         fprintf(OutFile,"{} L %g %g %g\n",-dx,-dy,-dz);
  1365.         fprintf(OutFile,"{} L %g %g %g\n",-dx,-dy, dz);
  1366.         fprintf(OutFile,"{} L %g %g %g\n", dx,-dy, dz);
  1367.         fprintf(OutFile,"{} L %g %g %g\n", dx, dy, dz);
  1368.         fprintf(OutFile,"{} L %g %g %g\n",-dx, dy, dz);
  1369.         fprintf(OutFile,"{} L %g %g %g\n",-dx,-dy, dz);
  1370.  
  1371.         fprintf(OutFile,"{} P %g %g %g\n", dx,-dy,-dz);
  1372.         fprintf(OutFile,"{} L %g %g %g\n", dx,-dy, dz);
  1373.         fprintf(OutFile,"{} P %g %g %g\n", dx, dy,-dz);
  1374.         fprintf(OutFile,"{} L %g %g %g\n", dx, dy, dz);
  1375.         fprintf(OutFile,"{} P %g %g %g\n",-dx, dy,-dz);
  1376.         fprintf(OutFile,"{} L %g %g %g\n",-dx, dy, dz);
  1377.     }
  1378.  
  1379.     if( *InfoSpaceGroup && (DrawUnitCell || KinemageFlag) )
  1380.     {   fputs("@group {unit cell} dominant",OutFile);
  1381.         fputs( (DrawAxes?"\n":" off\n"), OutFile );
  1382.         fprintf(OutFile,"@vectorlist {} color= %s\n",MageCol);
  1383.         OutputKinemageUnitCell();
  1384.     }
  1385. }
  1386.  
  1387.  
  1388. int WriteKinemageFile( name )
  1389.     char *name;
  1390. {
  1391.     register Chain __far *chain;
  1392.     register Real zoom;
  1393.  
  1394.     if( !Database )
  1395.         return(True);
  1396.  
  1397.     OutFile = fopen(name,"w");
  1398.     if( !OutFile )
  1399.     {   FatalScriptError(name);
  1400.         return(False);
  1401.     }
  1402.  
  1403.     fputs("@text\nRasMol v2.6 generated Kinemage\n \n",OutFile);
  1404.     if( *InfoMoleculeName )
  1405.         fprintf(OutFile,"Molecule name ....... %s\n",InfoMoleculeName);
  1406.     if( *InfoClassification )
  1407.         fprintf(OutFile,"Classification ...... %s\n",InfoClassification);
  1408.     if( *InfoIdentCode )
  1409.         fprintf(OutFile,"Brookhaven Code ..... %s\n",InfoIdentCode);
  1410.  
  1411.     fputs("@kinemage 1\n@caption RasMol v2.6 generated Kinemage\n",OutFile);
  1412.     fputs("@onewidth\n",OutFile);
  1413.  
  1414.     if( DialValue[3] != 0.0 )
  1415.     {   if( DialValue[3]<0.0 )
  1416.         {   zoom = DialValue[3];
  1417.         } else zoom = MaxZoom*DialValue[3];
  1418.         fprintf(OutFile,"zoom %g\n",zoom+1.0);
  1419.     }
  1420.  
  1421.     if( InfoChainCount>1 )
  1422.     {   for( chain=Database->clist; chain; chain=chain->cnext )
  1423.         {   fprintf(OutFile,"@group {chain %c}\n",chain->ident);
  1424.             WriteKinemageSpheres( chain );
  1425.             WriteKinemageBonds( chain );
  1426.             WriteKinemageRibbons( chain );
  1427.             WriteKinemageLabels( chain );
  1428.         }
  1429.     } else
  1430.     {   fputs("@group {molecule}\n",OutFile);
  1431.         chain = Database->clist;
  1432.         WriteKinemageSpheres( chain );
  1433.         WriteKinemageBonds( chain );
  1434.         WriteKinemageRibbons( chain );
  1435.         WriteKinemageLabels( chain );
  1436.     }
  1437.  
  1438.     WriteKinemageData();
  1439.     fclose(OutFile);
  1440. #ifdef APPLEMAC
  1441.     SetFileInfo(name,'MAGE','TEXT',135);
  1442. #endif
  1443.     return( True );
  1444. }
  1445.  
  1446.  int WritePOVRayFile( name )
  1447.     char *name;
  1448. {
  1449.     register ShadeDesc *shade;
  1450.     register Chain __far *chain;
  1451.     register Group __far *group;
  1452.     register Atom __far *aptr;
  1453.     register double x,y,z;
  1454.  
  1455.     if( !Database )
  1456.         return(True);
  1457.  
  1458.     OutFile = fopen(name,"w");
  1459.     if( !OutFile )
  1460.     {   FatalScriptError(name);
  1461.         return(False);
  1462.     }
  1463.  
  1464.     fprintf(OutFile,"// File: %s\n",name);
  1465.     fputs("// Creator: RasMol Version 2.6\n",OutFile);
  1466.     fputs("// Version: POV-Ray Version 2.2\n\n",OutFile);
  1467.  
  1468.     fputs("#include \"shapes.inc\"\n",OutFile);
  1469.     fputs("#include \"colors.inc\"\n",OutFile);
  1470.     fputs("#include \"textures.inc\"\n\n",OutFile);
  1471.  
  1472.     fputs("// Camera\ncamera {",OutFile);
  1473.     fprintf(OutFile,"    location <0, 0, %lg>\n",-Offset/250.0);
  1474.     fputs("    look_at <0, 0, 0>\n}\n\n",OutFile);
  1475.  
  1476.     fputs("// Light\nlight_source {<0, 20, -100>",OutFile);
  1477.     fputs(" color rgb <1, 1, 1>}\n\n",OutFile);
  1478.  
  1479.     fputs("// Objects\n",OutFile);
  1480.  
  1481.     ForEachAtom
  1482.         if( aptr->flag & SphereFlag )
  1483.         {   x = (double)aptr->xorg/250.0;
  1484.             y = (double)aptr->yorg/250.0;
  1485.             z = (double)aptr->zorg/250.0;
  1486.             fprintf(OutFile,"object {sphere {<%lg, %lg, %lg> %lg}\n",
  1487. #ifdef INVERT
  1488.                              x, -y, -z, aptr->radius/250.0 );
  1489. #else
  1490.                              x,  y, -z, aptr->radius/250.0 );
  1491. #endif
  1492.  
  1493.             fputs("  texture {\n",OutFile);
  1494.             shade = Shade+Colour2Shade(aptr->col);
  1495.             fprintf(OutFile,"    pigment {color rgb <%lg, %lg, %lg>}\n",
  1496.                     shade->r/255.0, shade->g/255.0, shade->b/255.0 );
  1497.             if( FakeSpecular )
  1498.                 fputs("    finish {phong 1}\n",OutFile);
  1499.             fputs("  }\n}\n",OutFile);
  1500.         }
  1501.  
  1502.     fclose(OutFile);
  1503. #ifdef APPLEMAC
  1504.     SetFileInfo(name,'ttxt','TEXT',133);
  1505. #endif
  1506.     return( True );
  1507. }
  1508.  
  1509.