home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Science / RasMol2 / script.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-28  |  39.5 KB  |  1,372 lines  |  [TEXT/KAHL]

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