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

  1. /* command.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, August 1995
  4.  * Version 2.6
  5.  */
  6. #include "rasmol.h"
  7.  
  8. #ifdef IBMPC
  9. #include <windows.h>
  10. #include <shellapi.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. #include <string.h>
  27. #include <ctype.h>
  28. #include <stdio.h>
  29.  
  30. #if !defined(IBMPC) && !defined(VMS) && !defined(APPLEMAC)
  31. #include <pwd.h>
  32. #endif
  33.  
  34. #define COMMAND
  35. #include "command.h"
  36. #include "tokens.h"
  37. #include "molecule.h"
  38. #include "infile.h"
  39. #include "abstree.h"
  40. #include "transfor.h"
  41. #include "render.h"
  42. #include "repres.h"
  43. #include "graphics.h"
  44. #include "pixutils.h"
  45. #include "outfile.h"
  46. #include "script.h"
  47.  
  48.  
  49. /* Macros for commonly used loops */
  50. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  51.              for(group=chain->glist;group;group=group->gnext)    \
  52.              for(ptr=group->alist;ptr;ptr=ptr->anext)
  53. #define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext)
  54.  
  55.  
  56. #define IsIdentChar(x)  ((isalnum(x))||((x)=='_')||((x)=='$'))
  57.  
  58.  
  59. #ifndef VMS
  60. #ifdef IBMPC
  61. #define DirChar  '\\'
  62. #else
  63. #define DirChar  '/'
  64. #endif
  65. #endif
  66.  
  67.  
  68. #define ErrSyntax        0
  69. #define ErrBigNum        1
  70. #define ErrBadOpt        2
  71. #define ErrParam         3
  72. #define ErrFilNam        4
  73. #define ErrBadLoad       5
  74. #define ErrNotNum        6
  75. #define ErrNotSep        7
  76. #define ErrNotBrac       8
  77. #define ErrNoCol         9
  78. #define ErrColour       10
  79. #define ErrBadArg       11
  80. #define ErrBadExpr      12
  81. #define ErrParen        13
  82. #define ErrScript       14
  83. #define ErrFunc         15
  84. #define ErrSetName      16
  85. #define ErrBadSet       17
  86. #define ErrInScrpt      18
  87. #define ErrOutScrpt     19
  88.  
  89.  
  90. static char *ErrorMsg[] = {
  91.     "Invalid command syntax",            /* ErrSyntax   */
  92.     "Parameter value too large",         /* ErrBigNum   */
  93.     "Invalid parameter setting",         /* ErrBadOpt   */
  94.     "Invalid parameter name",            /* ErrParam    */
  95.     "Filename string expected",          /* ErrFilNam   */
  96.     "Molecule database loaded",          /* ErrBadLoad  */
  97.     "Integer value expected",            /* ErrNotNum   */
  98.     "Comma separator missing",           /* ErrNotSep   */
  99.     "Close bracket ']' expected",        /* ErrNotBrac  */
  100.     "No colour specified",               /* ErrNoCol    */
  101.     "Unknown or incorrect colour",       /* ErrColour   */
  102.     "Invalid command argument",          /* ErrBadArg   */
  103.     "Syntax error in expression",        /* ErrBadExpr  */
  104.     "Close parenthesis ')' expected",    /* ErrParen    */
  105.     "Script command stack too deep",     /* ErrScript   */
  106.     "Open parenthesis '(' expected",     /* ErrFunc     */
  107.     "Invalid or missing atom set name",  /* ErrSetName  */
  108.     "Not enough memory to define set",   /* ErrBadSet   */
  109.     "Command disabled in script file",   /* ErrInScrpt  */
  110.         "Command invalid outside script"     /* ErrOutScrpt */
  111.     };
  112.  
  113.  
  114. typedef struct _HlpEntry {
  115.         struct _HlpEntry __far *next;
  116.         struct _HlpEntry __far *info;
  117.         char __far *keyword;
  118.         Long fpos;
  119.         } HlpEntry;
  120.  
  121. #define HelpPool   16
  122. static char *HelpFileName;
  123. static char HelpFileBuf[80];
  124. static HlpEntry __far *FreeInfo;
  125. static HlpEntry __far *HelpInfo;
  126.  
  127.  
  128. #define STACKSIZE  10
  129. static char *NameStack[STACKSIZE];
  130. static FILE *FileStack[STACKSIZE];
  131. static int LineStack[STACKSIZE];
  132.  
  133. #define HISTSIZE    4096
  134. #define HISTMASK    4095
  135. static char HistBuff[HISTSIZE];
  136. static int MinHist,MaxHist;
  137. static int CurHist;
  138.  
  139. static char *CurPrompt;
  140. static int CurPos,MaxPos;
  141.  
  142. static int TokenLength;
  143. static Long TokenValue;
  144. static char TokenIdent[128];
  145. static char *TokenStart;
  146. static char *TokenPtr;
  147. static int CurToken;
  148.  
  149.  
  150. static int RVal, GVal, BVal;
  151. static int AllowWrite;
  152.  
  153.  
  154. #ifdef FUNCPROTO
  155. /* Forward Declarations */
  156. int ProcessLine();
  157. int ExecuteCommand();
  158. int ExecuteIPCCommand( char __huge* );
  159. #endif
  160.  
  161. /* Forward Declarations */
  162. void ResumePauseCommand();
  163.  
  164.  
  165. static void UpdateLine()
  166. {
  167.     register int i;
  168.  
  169.     for( i=CurPos; i<MaxPos; i++ )
  170.     WriteChar(CurLine[i]);
  171.     WriteChar(' ');
  172.     for( i=MaxPos+1; i>CurPos; i-- )
  173.     WriteChar(0x08);
  174. }
  175.  
  176. static void CopyHistory()
  177. {
  178.     register int i;
  179.  
  180.     for( i=CurPos; i>0; i-- )
  181.     WriteChar(0x08);
  182.     for( i=0; i<MaxPos; i++ )
  183.     WriteChar(' ');
  184.     WriteChar(0x0D);
  185.     WriteString(CurPrompt);
  186.  
  187.     CurPos = 0;
  188.     if( (i=CurHist) != MaxHist )
  189.     while( HistBuff[i] )
  190.     {   CurLine[CurPos++] = HistBuff[i];
  191.         WriteChar(HistBuff[i]);
  192.         i = (i+1) & HISTMASK;
  193.     }
  194.     CurLine[CurPos] = 0;
  195.     MaxPos = CurPos;
  196. }
  197.  
  198.  
  199. int ProcessCharacter( ch )
  200.     int ch;
  201. {
  202.     register int i;
  203.  
  204.     if( !ch ) return( False );
  205.  
  206.     if( IsPaused )
  207.     {   ResumePauseCommand();
  208.         return( False );
  209.     }
  210.  
  211.     if( (ch>=' ') && (ch<='~') )
  212.     {   if( MaxPos<MAXLINELEN )
  213.     {   for( i=MaxPos; i>CurPos; i-- )
  214.         CurLine[i] = CurLine[i-1];
  215.         CurLine[CurPos++] = ch;
  216.         CurLine[++MaxPos] = 0;
  217.  
  218.         WriteChar(ch);
  219.         if( CurPos<MaxPos )
  220.         UpdateLine();
  221.     } else 
  222.         WriteChar(0x07);
  223.     
  224.     } else
  225.     switch( ch )
  226.     {    case( 0x7f ):  /* DEL and ^H */
  227.          case( 0x08 ):  if( CurPos>0 )
  228.                 {   for( i=CurPos; i<=MaxPos; i++ )
  229.                     CurLine[i-1] = CurLine[i];
  230.                 CurPos--; MaxPos--;
  231.                 WriteChar(0x08);
  232.                 UpdateLine();
  233.                 }
  234.                 break;
  235.  
  236.          case( 0x04 ):  if( CurPos<MaxPos ) /* ^D */
  237.                 {   for( i=CurPos; i<MaxPos; i++ )
  238.                     CurLine[i] = CurLine[i+1];
  239.                 MaxPos--; UpdateLine();
  240.                 }
  241.                 break;
  242.  
  243.          case( 0x0d ):  /* ^M and ^J */
  244.          case( 0x0a ):  WriteChar('\n');
  245.                 if( MaxPos )
  246.                 for( i=0; i<=MaxPos; i++ )
  247.                 {    HistBuff[MaxHist] = CurLine[i];
  248.                      MaxHist=(MaxHist+1)&HISTMASK;
  249.                      if( MaxHist==MinHist )
  250.                      {   while( HistBuff[MinHist] )
  251.                          MinHist=(MinHist+1)&HISTMASK;
  252.                      MinHist=(MinHist+1)&HISTMASK;
  253.                      }
  254.                 }
  255.                 CommandActive = False;
  256.                 return( True );
  257.  
  258.          case( 0x02 ):  if( CurPos>0 )  /* ^B */
  259.                 {    WriteChar(0x08);
  260.                  CurPos--;
  261.                 }
  262.                 break;
  263.  
  264.          case( 0x06 ):  if( CurPos<MaxPos )  /* ^F */
  265.                 WriteChar(CurLine[CurPos++]);
  266.                 break;
  267.  
  268.          case( 0x01 ):  while( CurPos>0 )   /* ^A */
  269.                 {    WriteChar(0x08);
  270.                  CurPos--;
  271.                 }
  272.                 break;
  273.  
  274.          case( 0x05 ):  while( CurPos<MaxPos )  /* ^E */
  275.                 WriteChar(CurLine[CurPos++]);
  276.                 break;
  277.  
  278.          case( 0x0c ):  WriteChar('\n');    /* ^L */
  279.                 WriteString(CurPrompt);
  280.                 for( i=0; i<MaxPos; i++ )
  281.                 WriteChar(CurLine[i]);
  282.                 for( i=CurPos; i<MaxPos; i++ )
  283.                 WriteChar(0x08);
  284.                 break;
  285.  
  286.          case( 0x10 ):  if( CurHist != MinHist ) /* ^P */
  287.                 {   CurHist -= 2;
  288.                 if( CurHist<0 )
  289.                     CurHist += HISTSIZE;
  290.                 while( HistBuff[CurHist] )
  291.                     CurHist=CurHist?CurHist-1:HISTMASK;
  292.                 CurHist = (CurHist+1)&HISTMASK;
  293.                 CopyHistory();
  294.                 }
  295.                 break;
  296.  
  297.          case( 0x0e ):  if( CurHist != MaxHist ) /* ^N */
  298.                 {   while( HistBuff[CurHist] )
  299.                     CurHist = (CurHist+1)&HISTMASK;
  300.                 CurHist = (CurHist+1)&HISTMASK;
  301.                 CopyHistory();
  302.                 }
  303.                 break;
  304.     }
  305.     return( False );
  306. }
  307.  
  308.  
  309. void ResetCommandLine( state )
  310.      int state;
  311. {
  312.     if( state )
  313.     {   EnableMenus(state==1);
  314.     switch( CurState=state )
  315.     {   case(1):   CurPrompt="RasMol> ";            break;
  316.         case(2):   CurPrompt="PDB file name:";      break;
  317.         case(3):   CurPrompt="Image file name:";    break;
  318.         case(4):   CurPrompt="Molecule file name:"; break;
  319.     }
  320.     }
  321.  
  322.     if( CommandActive )
  323.     WriteChar('\n');
  324.     CommandActive = True;
  325.     WriteString(CurPrompt);
  326.  
  327.     CurHist = MaxHist;
  328.     CurPos = MaxPos = 0;
  329.     CurLine[0] = 0;
  330. }
  331.  
  332.  
  333.  
  334. static void CommandError( error )
  335.     register char *error;
  336. {
  337.     register char *ptr;
  338.     char buffer[40];
  339.  
  340.     if( TokenPtr )
  341.     {   if( FileDepth > -1 )
  342.     {   if( CommandActive )
  343.         WriteChar('\n');
  344.         CommandActive=False;
  345.         
  346.         WriteString(CurLine);
  347.         WriteChar('\n');
  348.     } else WriteString("        ");
  349.  
  350.     for( ptr=CurLine; ptr<TokenStart; ptr++ )
  351.         WriteChar(' ');
  352.     WriteString("^\n");
  353.     }
  354.  
  355.     if( FileDepth > -1 )
  356.     {   if( LineStack[FileDepth] )
  357.     {   if( NameStack[FileDepth] )
  358.         {   WriteChar('"');
  359.         WriteString(NameStack[FileDepth]);
  360.         WriteString("\",");
  361.         }
  362.         sprintf(buffer,"line %d: ",LineStack[FileDepth]);
  363.         WriteString(buffer);
  364.     } else
  365.     {   WriteString(NameStack[FileDepth]);
  366.         WriteString(": ");
  367.     }
  368.     }
  369.  
  370.     if( error )
  371.     {   WriteString(error);
  372.     WriteString("!\n");
  373.     }
  374.     CommandActive = False;
  375.     CurToken = 0;
  376. }
  377.  
  378.  
  379. static char *ProcessFileName( name )
  380.     char *name;
  381. {
  382. #if !defined(IBMPC) && !defined(VMS) && !defined(APPLEMAC)
  383.     register struct passwd *entry;
  384.     register char *temp;
  385.     char username[64];
  386. #endif
  387.     register char *ptr;
  388.  
  389.  
  390.     while( *name==' ' )
  391.     name++;
  392.  
  393. #if defined(IBMPC) || defined(VMS)
  394.     ptr = DataFileName;
  395.     while( *name && (*name!=' ') )
  396.     {   *ptr++ = ToUpper(*name);
  397.     name++;
  398.     }
  399. #else
  400. #ifdef APPLEMAC
  401.     ptr = DataFileName;
  402.     while( *name )
  403.     *ptr++ = *name++;
  404.  
  405. #else /* UNIX */
  406.     /* Perform filename globbing */
  407.     if( *name=='~' )
  408.     {   ptr = username;  name++;
  409.     while( *name && (*name!=' ') && (*name!='/') )
  410.         *ptr++ = *name++;
  411.     *ptr = '\0';
  412.  
  413.     ptr = DataFileName;
  414.     if( *username )
  415.     {   if( (entry=getpwnam(username)) )
  416.         {   temp = entry->pw_dir;
  417.         endpwent();
  418.         } else /* Unknown user! */
  419.         {   temp = username;
  420.         *ptr++ = '~';
  421.         }
  422.  
  423.     } else if( !(temp=(char*)getenv("HOME")) )
  424.         temp = ".";
  425.  
  426.     while( *temp )
  427.         *ptr++ = *temp++;
  428.     } else ptr = DataFileName;
  429.  
  430.     while( *name && (*name!=' ') )
  431.     *ptr++ = *name++;
  432. #endif
  433. #endif
  434.     *ptr = '\0';
  435.     return ptr;
  436. }
  437.  
  438.  
  439. #if !defined(IBMPC) && !defined(APPLEMAC) && !defined(VMS)
  440. #define MaxFileExt  4
  441. /* UNIX Compressed Filename extensions! */
  442. static char *FileExt[MaxFileExt] = { "", ".Z", ".gz", ".z" };
  443. #endif
  444.  
  445. static FILE *OpenDataFile( begin, end )
  446.     char *begin, *end;
  447. {
  448.     register FILE *fp;
  449. #if !defined(IBMPC) && !defined(APPLEMAC) && !defined(VMS)
  450.     register char *src, *dst;
  451.     register int i;
  452.     
  453.     for( i=0; i<MaxFileExt; i++ )
  454.     {   dst = end; src = FileExt[i];
  455.     while( (*dst++ = *src++) );
  456.     if( (fp=fopen(begin,"r")) )
  457.         break;
  458.     }
  459. #else
  460.     fp = fopen(begin,"r");
  461. #endif
  462.     *end = '\0';
  463.     return fp;
  464. }
  465.  
  466.  
  467. int FetchFile( format, info, name )
  468.     int format, info;
  469.     char *name;
  470. {
  471. #ifndef APPLEMAC
  472. #if !defined(IBMPC) && !defined(VMS)
  473.     register int comp;
  474. #endif /* UNIX */
  475.     register char *src,*dst;
  476.     char buffer[128];
  477. #endif /* APPLEMAC */
  478.  
  479.     register int done;
  480.     register FILE *fp;
  481.  
  482.     DataFileFormat = 0;
  483.     name = ProcessFileName(name);
  484.     fp = OpenDataFile(DataFileName,name);
  485.  
  486. #ifndef APPLEMAC
  487.     /* Try using a default file path! */
  488.     if( !fp )
  489.     {   switch( format )
  490.         {   case(FormatNMRPDB):
  491.         case(FormatPDB):     src = (char*)getenv("RASMOLPDBPATH");  break;
  492.         case(FormatMol2):    src = (char*)getenv("RASMOLMOL2PATH"); break;
  493.             case(FormatMMDB):    src = (char*)getenv("RASMOLMMDBPATH"); break;
  494.         case(FormatAlchemy): src = (char*)getenv("RASMOLMOLPATH");  break;
  495.         case(FormatMDL):     src = (char*)getenv("RASMOLMDLPATH");  break;
  496.         case(FormatXYZ):     src = (char*)getenv("RASMOLXYZPATH");  break;
  497.         default:             src = NULL;
  498.     }
  499.  
  500.     if( src && *src )
  501.     {   dst = buffer;
  502.         while( *src ) *dst++ = *src++;
  503. #ifndef VMS
  504.         if( *(dst-1) != DirChar )
  505.         *dst++ = DirChar;
  506. #endif
  507.  
  508.         src = DataFileName;
  509.         while( (*dst = *src++) )
  510. #ifndef VMS
  511.         if( *dst == DirChar )
  512.         {   break;
  513.         } else dst++;
  514. #else
  515.         dst++;
  516. #endif
  517.  
  518.         if( !(*dst) && (fp=OpenDataFile(buffer,dst)) )
  519.         {   dst = DataFileName;  src=buffer;
  520.         while( (*dst++ = *src++) );
  521.         }
  522.     }
  523.     }
  524. #endif /* APPLEMAC */
  525.  
  526.  
  527.     if( !fp )
  528.     {   *name = '\0';
  529.     if( CommandActive )
  530.         WriteChar('\n');
  531.     WriteString("Error: File '");
  532.     WriteString(DataFileName);
  533.     WriteString("' not found!\n\n");
  534.     CommandActive=False;
  535.     return( False );
  536.     }
  537.  
  538. #if !defined(IBMPC) && !defined(VMS) && !defined(APPLEMAC)
  539.     done = getc(fp);
  540.     if( done == 0x1f )
  541.     {   done = getc(fp);
  542.     fclose(fp);
  543.  
  544.     if( done == 0x9d )
  545.     {   sprintf(buffer,"uncompress -c %s 2> /dev/null\n",DataFileName);
  546.     } else if( done == 0x8b )
  547.     {   sprintf(buffer,"gzip -cdq %s 2> /dev/null\n",DataFileName);
  548.     } else /* bad magic number! */
  549.     {   if( CommandActive )
  550.         WriteChar('\n');
  551.         WriteString("Error: Unrecognised compression format!\n\n");
  552.         CommandActive=False;
  553.         return( False );
  554.     }
  555.    
  556.     comp = True;
  557.     if( !(fp=popen(buffer,"r")) )
  558.     {   if( CommandActive )
  559.         WriteChar('\n');
  560.         WriteString("Error: Unable to decompress file!\n\n");
  561.         CommandActive=False;
  562.         return( False );
  563.     }
  564.     } else /* Uncompressed! */
  565.     {   ungetc(done,fp);
  566.     comp = False;
  567.     }
  568. #endif
  569.  
  570.     switch( format )
  571.     {   case(FormatPDB):      done = LoadPDBMolecule(fp,False);  break;
  572.         case(FormatNMRPDB):   done = LoadPDBMolecule(fp,True);   break;
  573.         case(FormatMacroMod): done = LoadMacroModelMolecule(fp); break;
  574.         case(FormatAlchemy):  done = LoadAlchemyMolecule(fp);    break;
  575.     case(FormatCharmm):   done = LoadCharmmMolecule(fp);     break;
  576.         case(FormatBiosym):   done = LoadBiosymMolecule(fp);     break;
  577.         case(FormatMOPAC):    done = LoadMOPACMolecule(fp);      break;
  578.         case(FormatSHELX):    done = LoadSHELXMolecule(fp);      break;
  579.     case(FormatMol2):     done = LoadMol2Molecule(fp);       break;
  580.         case(FormatFDAT):     done = LoadFDATMolecule(fp);       break;
  581.     case(FormatMDL):      done = LoadMDLMolecule(fp);        break;
  582.     case(FormatXYZ):      done = LoadXYZMolecule(fp);        break;
  583. #ifdef CEXIOLIB
  584.         case(FormatCEX):      done = LoadCEXMolecule(fp);        break;
  585. #endif
  586.         default:              done = False;
  587.     }
  588.  
  589. #if !defined(IBMPC) && !defined(VMS) && !defined(APPLEMAC)
  590.     if( comp )
  591.     {   if( pclose(fp) )
  592.     {   if( CommandActive )
  593.         WriteChar('\n');
  594.         WriteString("Error: Unable to decompress file!\n\n");
  595.         CommandActive=False;
  596.         return(False);
  597.     }
  598.     } else fclose(fp);
  599. #else /* !defined(UNIX) */
  600.     fclose(fp);
  601. #endif
  602.  
  603.     if( !done ) 
  604.     {   return( False );
  605.     } else if( !Database ) 
  606.     return( True );
  607.  
  608.     if( info )
  609.     DescribeMolecule();
  610.     DataFileFormat = format;
  611.     AdviseUpdate(AdvName);
  612.     AdviseUpdate(AdvClass);
  613.     AdviseUpdate(AdvIdent);
  614.  
  615. #if !defined(IBMPC) && !defined(APPLEMAC)        
  616.     if( Interactive ) 
  617.        FetchEvent(False);
  618. #endif
  619.  
  620.     ReDrawFlag |= RFInitial;
  621.     if( InfoBondCount < (MainAtomCount+HetaAtomCount)-1 )
  622.     {   if( MainAtomCount+HetaAtomCount > 255 )
  623.         {   CreateMoleculeBonds(info,False);
  624.         } else CreateMoleculeBonds(info,True);
  625.     }
  626.     
  627.     /* Explicit Hydrogen Bonds! */
  628.     if( InfoHBondCount > 0 )
  629.         SetHBondStatus(True,True,0);
  630.  
  631.     InitialTransform();
  632.  
  633.     VoxelsClean = False;
  634.     ApplyTransform();
  635.     return( True );
  636. }
  637.  
  638.  
  639. void LoadScriptFile( fp, name )
  640.     FILE *fp;  char *name;
  641. {
  642.     register char *ptr;
  643.     register int ch,len;
  644.  
  645.     if( fp )
  646.     {   len = 1;
  647.     for( ptr=name; *ptr; ptr++ )
  648.         len++;
  649.  
  650.     FileDepth++;
  651.     ptr = (char*)malloc( len );
  652.     NameStack[FileDepth] = ptr;
  653.     while( (*ptr++ = *name++) );
  654.         FileStack[FileDepth] = fp;
  655.     LineStack[FileDepth] = 0;
  656.  
  657.     do {
  658.         len = 0;
  659.         ch = getc(fp);
  660.         while( (ch!='\n') && (ch!=EOF) )
  661.         {   if( len<MAXBUFFLEN )
  662.             CurLine[len++] = ch;
  663.         ch = getc(fp);
  664.         }
  665.  
  666.         LineStack[FileDepth]++;
  667.         if( len<MAXBUFFLEN )
  668.         {   CurLine[len] = '\0';
  669.         if( !ExecuteCommand() ) 
  670.                 {   if( IsPaused ) 
  671.                         return;
  672.                 } else break;
  673.         } else CommandError("Script command line too long");
  674.     } while( ch!=EOF );
  675.     free(NameStack[FileDepth]);
  676.     fclose( fp );
  677.     FileDepth--;
  678.     } else
  679.     {   CommandError( (char*)NULL );
  680.     WriteString("Cannot open script file '");
  681.     WriteString(name);  WriteString("'\n");
  682.     }
  683. }
  684.  
  685. #ifdef FUNCPROTO
  686. /* Function Prototypes */
  687. static int PrefixString( char __far*, char __far* );
  688. #endif
  689.  
  690.  
  691. static int PrefixString( str1, str2 )
  692.     register char __far *str1, __far *str2;
  693. {
  694.     while( *str1 == *str2++ )
  695.     if( *str1++ == '\0' )
  696.         return( True );
  697.     return( *str1 == '\0' );
  698. }
  699.  
  700.  
  701. static HlpEntry __far *EnterHelpInfo( text )
  702.     register char *text;
  703. {
  704.     register HlpEntry __far * __far *tmp;
  705.     register HlpEntry __far *ptr;
  706.     register int res,len,i;
  707.     register char ch;
  708.  
  709.     char keyword[32];
  710.  
  711.     ptr = (void __far*)0;
  712.     while( *text && (*text!='\n') )
  713.     {   while( *text && (*text!='\n') && (*text==' ') )
  714.         text++;
  715.  
  716.     len = 0;
  717.     while( *text && (*text!='\n') && (*text!=' ') )
  718.         if( len<31 )
  719.         {   ch = *text++;
  720.         keyword[len++] = ToUpper(ch);
  721.         } else text++;
  722.     keyword[len]='\0';
  723.  
  724.     if( ptr )
  725.     {   tmp = &ptr->info;
  726.         ptr = (void __far*)0;
  727.     } else tmp = &HelpInfo;
  728.  
  729.     while( *tmp )
  730.     {   res = _fstrcmp(keyword,(*tmp)->keyword);
  731.         if( res==0 ) /* Exact Match */
  732.         {   ptr = *tmp;
  733.         break;
  734.         } else if( res<0 )
  735.         break;
  736.         tmp = &(*tmp)->next;
  737.     }
  738.  
  739.     if( !ptr )
  740.     {   if( !FreeInfo )
  741.         {   ptr = (HlpEntry __far*)_fmalloc(HelpPool*sizeof(HlpEntry));
  742.         if( !ptr ) 
  743.             RasMolFatalExit("Command Error: Insufficient memory!");
  744.         for( i=1; i<HelpPool; i++ )
  745.         {   ptr->next = FreeInfo;
  746.             FreeInfo = ptr++;
  747.         }
  748.         } else
  749.         {   ptr = FreeInfo;
  750.         FreeInfo = ptr->next;
  751.         }
  752.  
  753.         ptr->keyword = (char __far*)_fmalloc(len+1);
  754.         for( i=0; i<=len; i++ )
  755.         ptr->keyword[i] = keyword[i];
  756.  
  757.         ptr->info = (void __far*)0;
  758.         ptr->next = *tmp;
  759.         ptr->fpos = 0;
  760.         *tmp = ptr;
  761.     }
  762.     }
  763.     return( ptr );
  764. }
  765.  
  766. static void InitHelpFile()
  767. {
  768.     register char *src,*dst;
  769.     register HlpEntry __far *fix;
  770.     register HlpEntry __far *ptr;
  771.     register FILE *fp;
  772.     register Long pos;
  773.  
  774.     char buffer[82];
  775.  
  776.  
  777.     HelpFileName = "rasmol.hlp";
  778.     fp=fopen(HelpFileName,"r");
  779.  
  780. #ifdef NEXT
  781.     if (!fp && (fp=openResourceFile(HelpFileName, HelpFileBuf, 79)))
  782.     HelpFileName = HelpFileBuf;
  783. #endif
  784.     if( !fp && (src=(char*)getenv("RASMOLPATH")) )
  785.     {   HelpFileName = dst = HelpFileBuf; 
  786.     while( *src )
  787.         *dst++ = *src++;
  788. #ifndef VMS
  789.     if( (dst!=HelpFileBuf) && (*(dst-1)!=DirChar) )
  790.         *dst++ = DirChar;
  791. #endif
  792.  
  793.     src = "rasmol.hlp"; 
  794.     while( (*dst++ = *src++) );
  795.     fp = fopen(HelpFileName,"r");
  796.     }
  797.  
  798. #ifdef RASMOLDIR
  799.     if( !fp )
  800.     {   src = RASMOLDIR;
  801.     HelpFileName = dst = HelpFileBuf;
  802.     while( *src )
  803.         *dst++ = *src++;
  804. #ifndef VMS
  805.     if( (dst!=HelpFileBuf) && (*(dst-1)!=DirChar) )
  806.         *dst++ = DirChar;
  807. #endif
  808.  
  809.     src = "rasmol.hlp"; 
  810.     while( (*dst++ = *src++) );
  811.     fp = fopen(HelpFileName,"r");
  812.     }
  813. #endif
  814.  
  815.     if( !fp )
  816.     {   if( CommandActive )
  817.         WriteChar('\n');
  818.     CommandActive = False;
  819.     
  820.     WriteString("Unable to find RasMol help file!\n");
  821.     HelpFileName = NULL;
  822.     return;
  823.     }
  824.  
  825.     pos = 0;
  826.     fgets(buffer,80,fp);
  827.     while( !feof(fp) )
  828.     {    fix = (void __far*)0;
  829.      while( *buffer=='?' )
  830.      {   if( (ptr = EnterHelpInfo(buffer+1)) )
  831.          {   ptr->info = fix;
  832.          fix = ptr;
  833.          }
  834.  
  835.          pos = ftell(fp);
  836.          if( !fgets(buffer,80,fp) )
  837.          break;
  838.      }
  839.  
  840.      while( fix )
  841.      {   ptr = fix->info;
  842.          fix->info = (void __far*)0;
  843.          fix->fpos = pos;
  844.          fix = ptr;
  845.      }
  846.  
  847.      while( fgets(buffer,80,fp) )
  848.          if( *buffer=='?' )
  849.          break;
  850.     }
  851.     fclose(fp);
  852. }
  853.  
  854. static void FindHelpInfo()
  855. {
  856.     register HlpEntry __far * __far *tmp;
  857.     register HlpEntry __far *ptr;
  858.     register int res,len;
  859.     register Long pos;
  860.     register FILE *fp;
  861.     register char ch;
  862.  
  863.     char keyword[32];
  864.     char buffer[82];
  865.  
  866.     while( *TokenPtr && (*TokenPtr==' ') )
  867.     TokenPtr++;
  868.  
  869.     if( *TokenPtr )
  870.     {   ptr = NULL;
  871.     do {
  872.         len = 0;
  873.         while( *TokenPtr && (*TokenPtr!=' ') )
  874.         if( len<31 )
  875.         {   ch = *TokenPtr++;
  876.             keyword[len++] = ToUpper(ch);
  877.         } else TokenPtr++;
  878.         keyword[len]='\0';
  879.  
  880.         if( ptr )
  881.         {   tmp = &ptr->info;
  882.         ptr = (void __far*)0;
  883.         } else tmp = &HelpInfo;
  884.  
  885.         while( *tmp )
  886.         {   res = _fstrcmp(keyword,(*tmp)->keyword);
  887.         if( res<0 )
  888.         {   if( PrefixString(keyword,(*tmp)->keyword) )
  889.             {   ptr = *tmp;
  890.             if( ptr->next && 
  891.                 PrefixString(keyword,ptr->next->keyword) )
  892.             {   if( CommandActive ) WriteChar('\n');
  893.                 WriteString("Ambiguous help topic requested!\n");
  894.                 CommandActive = False;
  895.                 return;
  896.             } else break;
  897.             } else break;
  898.         } else if( res==0 ) 
  899.         {   ptr = *tmp;
  900.             break;
  901.         }
  902.         tmp = &(*tmp)->next;
  903.         }
  904.  
  905.         while( *TokenPtr && (*TokenPtr==' ') )
  906.         TokenPtr++;
  907.     } while( *TokenPtr && ptr );
  908.  
  909.     if( !ptr || !ptr->fpos )
  910.     {   if( CommandActive )
  911.         WriteChar('\n');
  912.         WriteString("No available help on requested topic!\n");
  913.         CommandActive=False;
  914.         return;
  915.     } else pos=ptr->fpos;
  916.     } else pos=0;
  917.  
  918.  
  919.     if( !(fp=fopen(HelpFileName,"r")) )
  920.     RasMolFatalExit("Command Error: Unable to reopen help file!");
  921.  
  922.     if( CommandActive )
  923.     WriteChar('\n');
  924.     CommandActive = False;
  925.  
  926.     fseek(fp,pos,0);
  927.     while( fgets(buffer,80,fp) )
  928.     if( *buffer!='?' )
  929.     {   WriteString(buffer);
  930.     } else break;
  931.     fclose(fp);
  932. }
  933.  
  934.  
  935. static int LookUpKeyword()
  936. {
  937.     register int mid,res;
  938.     register int lo, hi;
  939.  
  940.     if( TokenLength>MAXKEYLEN )
  941.     return( IdentTok );
  942.  
  943.     lo = KeyLen[TokenLength-1];
  944.     hi = KeyLen[TokenLength]-1;
  945.  
  946.     while( hi>=lo )
  947.     {   mid = (hi+lo)>>1;
  948.     res = _fstrcmp(TokenIdent,Keyword[mid].ident);
  949.     if( !res ) return( Keyword[mid].token );
  950.  
  951.     if( res>0 )
  952.     {      lo = mid+1;
  953.     } else hi = mid-1;
  954.     }
  955.     return( IdentTok );
  956. }
  957.  
  958.  
  959. static int FetchToken()
  960. {
  961.     register char ch;
  962.  
  963.     CurToken = 0;
  964.     while( True )
  965.     {    ch = *TokenPtr++;
  966.      if( !ch || (ch=='#') ) 
  967.          return(0);
  968.      if( isspace(ch) )
  969.          continue;
  970.  
  971.      TokenStart = TokenPtr-1;
  972.      if( isalpha(ch) )
  973.      {   TokenLength = 1;
  974.          *TokenIdent = ToUpper(ch);
  975.          while( IsIdentChar(*TokenPtr) && (TokenLength<32) )
  976.          {   ch = *TokenPtr++;
  977.          TokenIdent[TokenLength++] = ToUpper(ch);
  978.          }
  979.          if( TokenLength==32 )
  980.          {   CommandError("Identifier too long");
  981.          return(0);
  982.          } else TokenIdent[TokenLength] = '\0';
  983.          return( CurToken = LookUpKeyword() );
  984.  
  985.      } else if( isdigit(ch) )
  986.      {   TokenValue = ch-'0';
  987.          while( isdigit(*TokenPtr) )
  988.          TokenValue = 10*TokenValue + (*TokenPtr++)-'0';
  989.          return( CurToken = NumberTok );
  990.  
  991.      } else if( (ch=='\'') || (ch=='\"') || (ch=='`') )
  992.      {   TokenLength = 0;
  993.          while( *TokenPtr && (TokenLength<128) && (*TokenPtr!=ch) )
  994.          TokenIdent[TokenLength++] = *TokenPtr++;
  995.  
  996.          if( ch != *TokenPtr )
  997.          {   if( *TokenPtr )
  998.          {   CommandError("String constant unterminated");
  999.          } else CommandError("String constant too long");
  1000.          return( 0 );
  1001.          } else TokenPtr++;
  1002.  
  1003.          TokenIdent[TokenLength]='\0';
  1004.          return( CurToken = StringTok );
  1005.      } else if( ispunct(ch) )
  1006.          return( CurToken = ch );
  1007.     }
  1008. }
  1009.  
  1010.  
  1011. static int NextIf( token, error )
  1012.     int token, error;
  1013. {
  1014.     if( FetchToken()!=token )
  1015.     {   CommandError(ErrorMsg[error]);
  1016.     return( True );
  1017.     } else return( False );
  1018. }
  1019.  
  1020.  
  1021. static void FetchFloat( value, scale )
  1022.     Long value;  int scale;
  1023. {
  1024.     register int count;
  1025.     register int mant;
  1026.  
  1027.     if( !value && !isdigit(*TokenPtr) )
  1028.     {   CommandError("Invalid floating point number");
  1029.     TokenValue = 0;
  1030.     return;
  1031.     }
  1032.  
  1033.     mant = 0;
  1034.     count = 1;
  1035.     while( isdigit(*TokenPtr) )
  1036.     {   if( count < scale )
  1037.     {   mant = 10*mant + (*TokenPtr-'0');
  1038.         count *= 10;
  1039.     }
  1040.     TokenPtr++;
  1041.     }
  1042.  
  1043.     mant = (scale*mant)/count;
  1044.     TokenValue = value*scale + mant;
  1045. }
  1046.  
  1047.  
  1048. static int ParseColour()
  1049. {
  1050.     switch( CurToken )
  1051.     {   case(BlueTok):        RVal=0;   GVal=0;   BVal=255; break;
  1052.     case(BlackTok):       RVal=0;   GVal=0;   BVal=0;   break;
  1053.     case(CyanTok):        RVal=0;   GVal=255; BVal=255; break;
  1054.     case(GreenTok):       RVal=0;   GVal=255; BVal=0;   break;
  1055.     case(GreenblueTok):   RVal=46;  GVal=139; BVal=87;  break;
  1056.     case(MagentaTok):     RVal=255; GVal=0;   BVal=255; break;
  1057.     case(OrangeTok):      RVal=255; GVal=165; BVal=0;   break;
  1058.     case(PurpleTok):      RVal=160; GVal=32;  BVal=240; break;
  1059.     case(RedTok):         RVal=255; GVal=0;   BVal=0;   break;
  1060.     case(RedorangeTok):   RVal=255; GVal=69;  BVal=0;   break;
  1061.     case(VioletTok):      RVal=238; GVal=130; BVal=238; break;
  1062.     case(WhiteTok):       RVal=255; GVal=255; BVal=255; break; 
  1063.     case(YellowTok):      RVal=255; GVal=255; BVal=0;   break;
  1064.  
  1065.     case('['):    RVal = GVal = BVal = 0;
  1066.  
  1067.               if( NextIf(NumberTok,ErrNotNum) ) { return(False);
  1068.               } else if( TokenValue>255 )
  1069.               {   CommandError(ErrorMsg[ErrBigNum]); return( False );
  1070.               } else RVal = (int)TokenValue;
  1071.  
  1072.               if( NextIf(',',ErrNotSep) ) return(False);
  1073.               if( NextIf(NumberTok,ErrNotNum) ) { return(False);
  1074.               } else if( TokenValue>255 )
  1075.               {   CommandError(ErrorMsg[ErrBigNum]); return( False );
  1076.               } else GVal = (int)TokenValue;
  1077.  
  1078.               if( NextIf(',',ErrNotSep) ) return(False);
  1079.               if( NextIf(NumberTok,ErrNotNum) ) { return(False);
  1080.               } else if( TokenValue>255 )
  1081.               {   CommandError(ErrorMsg[ErrBigNum]); return( False );
  1082.               } else BVal = (int)TokenValue;
  1083.  
  1084.               return( !NextIf(']',ErrNotBrac) );
  1085.  
  1086.     case(IdentTok): if( Interactive )
  1087.             return( LookUpColour(TokenIdent,&RVal,&GVal,&BVal) );
  1088.               
  1089.     default:  return(False);
  1090.     }
  1091.     return( True );
  1092. }
  1093.  
  1094.  
  1095. static void CentreZoneExpr( expr )
  1096.     Expr *expr;
  1097. {
  1098.     register Real x, y, z;
  1099.     register Long count;
  1100.  
  1101.     if( !Database )
  1102.     return;
  1103.  
  1104.     count = 0;
  1105.     x = y = z = 0.0;
  1106.     for( QChain=Database->clist; QChain; QChain=QChain->cnext )
  1107.     for( QGroup=QChain->glist; QGroup; QGroup=QGroup->gnext )
  1108.         for( QAtom=QGroup->alist; QAtom; QAtom=QAtom->anext )
  1109.         if( EvaluateExpr(expr) )
  1110.         {   x += (Real)QAtom->xorg;
  1111.             y += (Real)QAtom->yorg;
  1112.             z += (Real)QAtom->zorg;
  1113.             count++;
  1114.         }
  1115.  
  1116.     if( count )
  1117.     {   CenX = (Long)(x/count);
  1118.     CenY = (Long)(y/count);
  1119.     CenZ = (Long)(z/count);
  1120.     } else
  1121.     {   if( CommandActive ) WriteChar('\n');
  1122.     WriteString("No Atoms to Centre!\n");
  1123.     CommandActive = False;
  1124.     }
  1125. }
  1126.  
  1127.  
  1128. static Expr *ParseRange( neg )
  1129.     int neg;
  1130. {
  1131.     register Expr *tmp1,*tmp2;
  1132.     register char ch;
  1133.  
  1134.     tmp1 = AllocateNode();
  1135.     tmp1->type = OpLftProp|OpRgtVal;
  1136.     tmp1->rgt.val = neg? -(int)TokenValue : (int)TokenValue;
  1137.     tmp1->lft.val = PropResId;
  1138.  
  1139.     if( *TokenPtr == '-' )
  1140.     {   TokenPtr++;
  1141.     neg = (*TokenPtr=='-');
  1142.     if( neg ) TokenPtr++;
  1143.     FetchToken();
  1144.  
  1145.     if( CurToken != NumberTok )
  1146.     {   CommandError(ErrorMsg[ErrNotNum]);
  1147.         DeAllocateExpr( tmp1 );
  1148.         return( (Expr*)NULL );
  1149.     }
  1150.  
  1151.     tmp1->type |= OpMoreEq;
  1152.     tmp2 = AllocateNode();
  1153.     tmp2->rgt.ptr = tmp1;
  1154.     tmp2->type = OpAnd;
  1155.  
  1156.     tmp1 = AllocateNode();
  1157.     tmp1->type = OpLftProp|OpRgtVal|OpLessEq;
  1158.     tmp1->rgt.val = neg? -(int)TokenValue : (int)TokenValue;
  1159.     tmp1->lft.val = PropResId;
  1160.     tmp2->lft.ptr = tmp1;
  1161.     tmp1 = tmp2;
  1162.     } else tmp1->type |= OpEqual;
  1163.  
  1164.     if( *TokenPtr == ':' )
  1165.     TokenPtr++;
  1166.  
  1167.     ch = *TokenPtr;
  1168.     if( isalnum(ch) )
  1169.     {   ch = ToUpper(ch);
  1170.     TokenPtr++;
  1171.  
  1172.     tmp2 = AllocateNode();
  1173.     tmp2->type = OpAnd;
  1174.     tmp2->rgt.ptr = tmp1;
  1175.  
  1176.     tmp1 = AllocateNode();
  1177.     tmp1->type = OpEqual | OpLftProp | OpRgtVal;
  1178.     tmp1->lft.val = PropChain;               
  1179.     tmp1->rgt.val = ch;
  1180.  
  1181.     tmp2->lft.ptr = tmp1;
  1182.     tmp1 = tmp2;
  1183.     } else if( (ch=='?') || (ch=='%') || (ch=='*') )
  1184.     TokenPtr++;
  1185.  
  1186.     FetchToken();
  1187.     return( tmp1 );
  1188. }
  1189.  
  1190.  
  1191. static Expr *ParseExpression( level )
  1192.     int level;
  1193. {
  1194.     register Expr *tmp1,*tmp2;
  1195.     register int done, pred;
  1196.     register int neg;
  1197.  
  1198.     switch( level )
  1199.     {    case(0): /* Disjunctions */
  1200.           tmp1 = ParseExpression(1);
  1201.           while( (CurToken==OrTok) || (CurToken=='|') ||
  1202.              (CurToken==',') )
  1203.           {   if( CurToken=='|' )
  1204.               {   if( FetchToken()=='|' )
  1205.                   FetchToken();
  1206.               } else FetchToken();
  1207.  
  1208.               tmp2 = AllocateNode();
  1209.               tmp2->type = OpOr;
  1210.               tmp2->lft.ptr = tmp1;
  1211.               tmp2->rgt.ptr = NULL;
  1212.               if( !(tmp1=ParseExpression(1)) )
  1213.               {   DeAllocateExpr(tmp2);
  1214.               return( tmp1 );
  1215.               }
  1216.               tmp2->rgt.ptr = tmp1;
  1217.               tmp1 = tmp2;
  1218.           }
  1219.           return( tmp1 );
  1220.  
  1221.      case(1): /* Conjunctions */
  1222.           tmp1 = ParseExpression(2);
  1223.           while( (CurToken==AndTok) || (CurToken=='&') )
  1224.           {   if( CurToken=='&' )
  1225.               {   if( FetchToken()=='&' )
  1226.                   FetchToken();
  1227.               } else FetchToken();
  1228.  
  1229.               tmp2 = AllocateNode();
  1230.               tmp2->type = OpAnd;
  1231.               tmp2->lft.ptr = tmp1;
  1232.               tmp2->rgt.ptr = NULL;
  1233.               if( !(tmp1=ParseExpression(2)) )
  1234.               {   DeAllocateExpr(tmp2);
  1235.               return( tmp1 );
  1236.               }
  1237.               tmp2->rgt.ptr = tmp1;
  1238.               tmp1 = tmp2;
  1239.           }
  1240.           return( tmp1 );
  1241.  
  1242.      case(2): /* Primitives */
  1243.           if( IsPredTok(CurToken) || (CurToken==BackboneTok) )
  1244.           {   switch( CurToken )
  1245.               {   case(HelixTok):    if( InfoHelixCount<0 )
  1246.                          DetermineStructure(False);
  1247.                          pred = PredHelix;
  1248.                          break;
  1249.               case(SheetTok):    if( InfoLadderCount<0 )
  1250.                          DetermineStructure(False);
  1251.                          pred = PredSheet;
  1252.                          break;
  1253.               case(TurnTok):     if( InfoTurnCount<0 )
  1254.                          DetermineStructure(False);
  1255.                          pred = PredTurn;
  1256.                          break;
  1257.               case(CystineTok):  if( InfoSSBondCount<0 )
  1258.                          FindDisulphideBridges();
  1259.                          pred = PredCystine;     
  1260.                          break;
  1261.               case(BackboneTok): pred = PredMainChain;   break;
  1262.               case(SelectedTok): pred = PropSelect;      break;
  1263.               default:  pred = PredAbsChr(PredTokOrd(CurToken));
  1264.               }
  1265.  
  1266.               tmp1 = AllocateNode();
  1267.               tmp1->type = OpConst|OpLftProp|OpRgtVal;
  1268.               tmp1->lft.val = pred;
  1269.               FetchToken();
  1270.               return( tmp1 );
  1271.  
  1272.           } else if( IsPropTok(CurToken) )
  1273.           {   tmp1 = AllocateNode();
  1274.               tmp1->type = OpLftProp|OpRgtVal;
  1275.               switch( CurToken )
  1276.               {   case(TemperatureTok): pred = PropTemp;    break;
  1277.               case(RadiusTok):      pred = PropRad;     break;
  1278.               case(AtomNoTok):      pred = PropIdent;   break;
  1279.               case(ElemNoTok):      pred = PropElemNo;  break;
  1280.               case(ResNoTok):       pred = PropResId;   break;
  1281.                           case(ModelTok):       pred = PropModel;   break;
  1282.               }
  1283.               tmp1->lft.val = pred;
  1284.  
  1285.               FetchToken();
  1286.               if( CurToken=='=' )
  1287.               {   tmp1->type |= OpEqual;
  1288.               if( FetchToken()=='=' )
  1289.                   FetchToken();
  1290.               } else if( CurToken=='<' )
  1291.               {   FetchToken();
  1292.               if( CurToken=='>' )
  1293.               {   tmp1->type |= OpNotEq;
  1294.                   FetchToken();
  1295.               } else if( CurToken=='=' )
  1296.               {   tmp1->type |= OpLessEq;
  1297.                   FetchToken();
  1298.               } else tmp1->type |= OpLess;
  1299.               } else if( CurToken=='>' )
  1300.               {   if( FetchToken()=='=' )
  1301.               {   tmp1->type |= OpMoreEq;
  1302.                   FetchToken();
  1303.               } else tmp1->type |= OpMore;
  1304.               } else if( (CurToken=='!') || (CurToken=='/') )
  1305.               {   if( NextIf('=',ErrBadExpr) )
  1306.               {   DeAllocateExpr( tmp1 );
  1307.                   return( (Expr*)NULL );
  1308.               } else tmp1->type |= OpNotEq;
  1309.               FetchToken();
  1310.               } else
  1311.               {   CommandError(ErrorMsg[ErrBadExpr]);
  1312.               DeAllocateExpr( tmp1 );
  1313.               return( (Expr*)NULL );
  1314.               }
  1315.  
  1316.  
  1317.               if( CurToken == '-' )
  1318.               {   FetchToken();
  1319.               neg = True;
  1320.               } else neg = False;
  1321.  
  1322.               if( CurToken!=NumberTok )
  1323.               {   CommandError(ErrorMsg[ErrNotNum]);
  1324.               DeAllocateExpr( tmp1 );
  1325.               return( (Expr*)NULL );
  1326.               } 
  1327.  
  1328.               if( neg )
  1329.               {     tmp1->rgt.val = -(int)TokenValue; 
  1330.               } else tmp1->rgt.val = (int)TokenValue;
  1331.               FetchToken();
  1332.               return( tmp1 );
  1333.               
  1334.           } else switch( CurToken )
  1335.           {   case('('):    FetchToken();
  1336.                     if( !(tmp1=ParseExpression(0)) )
  1337.                     return( (Expr*)NULL );
  1338.  
  1339.                     if( CurToken!=')' )
  1340.                     {   CommandError(ErrorMsg[ErrParen]);
  1341.                     DeAllocateExpr( tmp1 );
  1342.                     return( (Expr*)NULL );
  1343.                     }
  1344.                     FetchToken();
  1345.                     return(tmp1);
  1346.  
  1347.               case('!'): case('~'):
  1348.               case(NotTok): FetchToken();
  1349.                     if( !(tmp1=ParseExpression(2)) )
  1350.                     return( (Expr*)NULL );
  1351.  
  1352.                     tmp2 = AllocateNode();
  1353.                     tmp2->type = OpNot | OpRgtVal;
  1354.                     tmp2->lft.ptr = tmp1;
  1355.                     return( tmp2 );
  1356.  
  1357.               case('-'):    if( NextIf(NumberTok,ErrNotNum) )
  1358.                     return( (Expr*)NULL );
  1359.                     return( ParseRange(True) );
  1360.  
  1361.               case(NumberTok):
  1362.                     return( ParseRange(False) );
  1363.  
  1364.               case(WithinTok):
  1365.                     if( NextIf('(',ErrFunc) )
  1366.                     return( (Expr*)NULL );
  1367.  
  1368.                     FetchToken();
  1369.                     if( CurToken==NumberTok )
  1370.                     {   if( *TokenPtr=='.' )
  1371.                     {   TokenPtr++;
  1372.                         FetchFloat(TokenValue,250);
  1373.                     }
  1374.                     } else if( CurToken!='.' )
  1375.                     {   CommandError(ErrorMsg[ErrNotNum]);
  1376.                     return( (Expr*)NULL );
  1377.                     } else FetchFloat(0,250);
  1378.  
  1379.                     if( TokenValue>10000 )
  1380.                     {   CommandError(ErrorMsg[ErrBigNum]);
  1381.                     return( (Expr*)NULL );
  1382.                     } else pred = (int)TokenValue;
  1383.                     if( NextIf(',',ErrNotSep) )
  1384.                     return( (Expr*)NULL );
  1385.  
  1386.                     FetchToken();
  1387.                     if( !(tmp1=ParseExpression(0)) )
  1388.                     return( (Expr*)NULL );
  1389.  
  1390.                     if( CurToken!=')' )
  1391.                     {   CommandError(ErrorMsg[ErrParen]);
  1392.                     DeAllocateExpr( tmp1 );
  1393.                     return( (Expr*)NULL );
  1394.                     }
  1395.  
  1396.                     FetchToken();
  1397.                     if( !pred )
  1398.                     return( tmp1 );
  1399.  
  1400.                     tmp2 = AllocateNode();
  1401.                     tmp2->type = OpWithin;
  1402.                     tmp2->lft.limit = (Long)pred*pred;
  1403.                     tmp2->rgt.set = BuildAtomSet(tmp1);
  1404.                     DeAllocateExpr(tmp1);
  1405.                     return( tmp2 );
  1406.  
  1407.               default:      if( CurToken==IdentTok )
  1408.                     {   tmp1 = LookUpSetExpr(TokenIdent);
  1409.                     if( !tmp1 ) 
  1410.                         tmp1 = LookUpElement(TokenIdent);
  1411.  
  1412.                     if( tmp1 )
  1413.                     {   FetchToken();
  1414.                         return(tmp1);
  1415.                     }
  1416.                     }
  1417.  
  1418.                     TokenPtr = TokenStart;
  1419.                     done = ParsePrimitiveExpr(&TokenPtr);
  1420.                     FetchToken();
  1421.  
  1422.                     if( !done )
  1423.                     {   CommandError(ErrorMsg[ErrBadExpr]);
  1424.                     DeAllocateExpr( QueryExpr );
  1425.                     return( (Expr*)NULL );
  1426.                     } else return( QueryExpr );
  1427.           }
  1428.     }
  1429.     return( (Expr*)NULL );
  1430. }
  1431.  
  1432. static void ExecuteSetCommand()
  1433. {
  1434.     register int option;
  1435.  
  1436.     switch( FetchToken() )
  1437.     {   case(SlabTok):
  1438.         case(SlabModeTok):
  1439.         option = -1;
  1440.         FetchToken();
  1441.         if( CurToken==RejectTok )
  1442.         {   option = SlabReject;
  1443.         } else if( CurToken==HalfTok )
  1444.         {   option = SlabHalf;
  1445.         } else if( CurToken==HollowTok )
  1446.         {   option = SlabHollow;
  1447.         } else if( CurToken==SolidTok )
  1448.         {   option = SlabClose;
  1449.         } else if( CurToken==SectionTok )
  1450.         option = SlabSection;
  1451.  
  1452.         if( option != -1 )
  1453.         {   if( UseSlabPlane && (SlabMode!=option) )
  1454.             ReDrawFlag |= RFRefresh;
  1455.         SlabMode = option;
  1456.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1457.         break;
  1458.  
  1459.     case(ShadowTok):
  1460.         FetchToken();
  1461.         if( CurToken==TrueTok )
  1462.         {   UseShadow = True;
  1463.         ReviseInvMatrix();
  1464.         VoxelsClean = False;
  1465.         UseSlabPlane = False;
  1466.         ReDrawFlag |= RFRefresh;
  1467.         ReAllocBuffers();
  1468.         } else if( CurToken==FalseTok )
  1469.         {   ReDrawFlag |= RFRefresh;
  1470.         UseShadow = False;
  1471.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1472.         break;
  1473.                   
  1474.     case(SpecularTok):
  1475.         FetchToken();
  1476.         if( CurToken==TrueTok )
  1477.         {   FakeSpecular = True;
  1478.         ReDrawFlag |= RFColour;
  1479.         } else if( CurToken==FalseTok )
  1480.         {   FakeSpecular = False;
  1481.         ReDrawFlag |= RFColour;
  1482.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1483.         break;
  1484.  
  1485.     case(SpecPowerTok):
  1486.         FetchToken();
  1487.         if( !CurToken )
  1488.         {   SpecPower = 8;
  1489.         ReDrawFlag |= RFColour;
  1490.         } else if( CurToken==NumberTok )
  1491.         {   if( TokenValue<=100 )
  1492.         {   ReDrawFlag |= RFColour;
  1493.             SpecPower = (int)TokenValue;
  1494.         } else 
  1495.             CommandError(ErrorMsg[ErrBigNum]);
  1496.         } else CommandError(ErrorMsg[ErrNotNum]);
  1497.         break;
  1498.  
  1499.     case(AmbientTok):
  1500.         FetchToken();
  1501.         if( !CurToken )
  1502.         {   ReDrawFlag |= RFColour;
  1503.         Ambient = DefaultAmbient;
  1504.         } else if( CurToken==NumberTok )
  1505.         {   if( TokenValue<=100 )
  1506.         {   Ambient = TokenValue/100.0;
  1507.             ReDrawFlag |= RFColour;
  1508.         } else
  1509.             CommandError(ErrorMsg[ErrBigNum]); 
  1510.         } else CommandError(ErrorMsg[ErrNotNum]);
  1511.         break;
  1512.  
  1513.     case(HeteroTok):
  1514.         FetchToken();
  1515.         if( CurToken==TrueTok )
  1516.         {   HetaGroups = True;
  1517.         } else if( CurToken==FalseTok )
  1518.         {   HetaGroups = False;
  1519.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1520.         break;
  1521.                   
  1522.     case(HydrogenTok):
  1523.         FetchToken();
  1524.         if( CurToken==TrueTok )
  1525.         {   Hydrogens = True;
  1526.         } else if( CurToken==FalseTok )
  1527.         {   Hydrogens = False;
  1528.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1529.         break;
  1530.                   
  1531.  
  1532.     case(BackgroundTok):
  1533.         FetchToken();
  1534.         if( !CurToken )
  1535.         {   CommandError(ErrorMsg[ErrNoCol]);
  1536.         } else if( ParseColour() )
  1537.         {   ReDrawFlag |= RFColour;
  1538.         BackR = RVal;
  1539.         BackG = GVal;
  1540.         BackB = BVal;
  1541. #ifndef IBMPC
  1542.         FBClear = False;
  1543. #endif
  1544.         } else if( CurToken )
  1545.         CommandError(ErrorMsg[ErrColour]);
  1546.         break;
  1547.  
  1548.     case(BondModeTok):
  1549.         FetchToken();
  1550.         if( !CurToken || (CurToken==AndTok) )
  1551.         {   ZoneBoth = True;
  1552.         } else if( CurToken==OrTok )
  1553.         {   ZoneBoth = False;
  1554.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1555.         break;
  1556.         
  1557.     case(HBondTok):
  1558.         FetchToken();
  1559.         if( (CurToken==BackboneTok) || (CurToken==MainChainTok) )
  1560.         {   ReDrawFlag |= RFRefresh;
  1561.         HBondMode = True;
  1562.         } else if( !CurToken || (CurToken==SidechainTok) )
  1563.         {   ReDrawFlag |= RFRefresh;
  1564.         HBondMode = False;
  1565.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1566.         break;
  1567.  
  1568.     case(SSBondTok):
  1569.         FetchToken();
  1570.         if( (CurToken==BackboneTok) || (CurToken==MainChainTok) )
  1571.         {   ReDrawFlag |= RFRefresh;
  1572.         SSBondMode = True;
  1573.         } else if( !CurToken || (CurToken==SidechainTok) )
  1574.         {   ReDrawFlag |= RFRefresh;
  1575.         SSBondMode = False;
  1576.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1577.         break;
  1578.  
  1579.     case(HourGlassTok):
  1580.         FetchToken();
  1581.         if( CurToken==TrueTok )
  1582.         {   UseHourGlass = True;
  1583.         } else if( CurToken==FalseTok )
  1584.         {   UseHourGlass = False;
  1585.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1586.         break;
  1587.  
  1588.     case(StrandsTok):
  1589.         FetchToken();
  1590.         if( !CurToken )
  1591.         {   ReDrawFlag |= RFRefresh;
  1592.         SplineCount = 5;
  1593.         } else if( CurToken==NumberTok )
  1594.         {   if( (TokenValue>0) && (TokenValue<=5) )
  1595.         {   SplineCount = (int)TokenValue;
  1596.             ReDrawFlag |= RFRefresh;
  1597.         } else if( TokenValue==9 )
  1598.         {   ReDrawFlag |= RFRefresh;
  1599.             SplineCount = 9;
  1600.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1601.         } else CommandError(ErrorMsg[ErrNotNum]);
  1602.         break;
  1603.  
  1604.     case(MouseTok):
  1605.         FetchToken();
  1606.         if( !CurToken || (CurToken==RasMolTok) )
  1607.         {   if( Interactive )
  1608.             SetMouseMode( MMRasMol );
  1609.         } else if( CurToken==InsightTok )
  1610.         {   if( Interactive )
  1611.             SetMouseMode( MMInsight );
  1612.         } else if( CurToken==QuantaTok )
  1613.         {   if( Interactive )
  1614.             SetMouseMode( MMQuanta );
  1615.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1616.         break;
  1617.  
  1618.     case(DisplayTok):
  1619.         FetchToken();
  1620.             /* Affect StereoMode Parameters?? */
  1621.         if( !CurToken || (CurToken==NormalTok) )
  1622.         {   ReDrawFlag |= RFRefresh | RFColour;
  1623.         DisplayMode = 0;
  1624.         } else if( CurToken==SelectedTok )
  1625.         {   ReDrawFlag |= RFRefresh | RFColour;
  1626.         DisplayMode = 1;
  1627.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1628.         break;
  1629.  
  1630.     case(AxesTok):
  1631.         FetchToken();
  1632.         if( !CurToken || (CurToken==FalseTok) )
  1633.         {   ReDrawFlag |= RFRefresh;
  1634.         DrawAxes = False;
  1635.         } else if( CurToken == TrueTok )
  1636.         {   ReDrawFlag |= RFRefresh;
  1637.         DrawAxes = True;
  1638.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1639.         break;
  1640.  
  1641.     case(BoundBoxTok):
  1642.         FetchToken();
  1643.         if( !CurToken || (CurToken==FalseTok) )
  1644.         {   ReDrawFlag |= RFRefresh;
  1645.         DrawBoundBox = False;
  1646.         } else if( CurToken == TrueTok )
  1647.         {   ReDrawFlag |= RFRefresh;
  1648.         DrawBoundBox = True;
  1649.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1650.         break;
  1651.  
  1652.     case(UnitCellTok):
  1653.         FetchToken();
  1654.         if( !CurToken || (CurToken==FalseTok) )
  1655.         {   ReDrawFlag |= RFRefresh;
  1656.         DrawUnitCell = False;
  1657.         } else if( CurToken == TrueTok )
  1658.         {   ReDrawFlag |= RFRefresh;
  1659.         DrawUnitCell = True;
  1660.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1661.         break;
  1662.  
  1663.     case(VectPSTok):
  1664.         FetchToken();
  1665.         if( !CurToken || (CurToken==FalseTok) )
  1666.         {   UseOutLine = False;
  1667.         } else if( CurToken == TrueTok )
  1668.         {   UseOutLine = True;
  1669.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1670.         break;
  1671.  
  1672.     case(KinemageTok):
  1673.         FetchToken();
  1674.         if( !CurToken || (CurToken==FalseTok) )
  1675.         {   KinemageFlag = False;
  1676.         } else if( CurToken == TrueTok )
  1677.         {   KinemageFlag = True;
  1678.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1679.         break;
  1680.  
  1681.     case(MenusTok):
  1682.         FetchToken();
  1683.         if( !CurToken || (CurToken==TrueTok) )
  1684.         {   EnableMenus(True);
  1685.         } else if( CurToken == FalseTok )
  1686.         {   EnableMenus(False);
  1687.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1688.         break;
  1689.  
  1690.     case(RadiusTok):
  1691.         FetchToken();
  1692.         if( !CurToken )
  1693.         {   ProbeRadius = SolventDots? 300 : 0;
  1694.         } else if( CurToken==NumberTok )
  1695.         {   if( *TokenPtr=='.' )
  1696.         {   TokenPtr++;
  1697.             FetchFloat(TokenValue,250);
  1698.         }
  1699.  
  1700.         if( TokenValue>500 )
  1701.         {   CommandError(ErrorMsg[ErrBigNum]);
  1702.         } else ProbeRadius = (int)TokenValue;
  1703.         } else if( CurToken=='.' )
  1704.         {   FetchFloat(0,250);
  1705.         if( TokenValue>500 )
  1706.         {   CommandError(ErrorMsg[ErrBigNum]);
  1707.         } else ProbeRadius = (int)TokenValue;
  1708.  
  1709.         } else CommandError(ErrorMsg[ErrNotNum]);
  1710.         break;
  1711.  
  1712.     case(SolventTok):
  1713.         FetchToken();
  1714.         if( !CurToken || (CurToken==FalseTok) )
  1715.         {   SolventDots = False;
  1716.         ProbeRadius = 0;
  1717.         } else if( CurToken == TrueTok )
  1718.         {   SolventDots = True;
  1719.         ProbeRadius = 300;
  1720.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1721.         break;
  1722.  
  1723.     case(FontSizeTok):
  1724.         FetchToken();
  1725.         if( CurToken==NumberTok )
  1726.         {   if( TokenValue<=32 )
  1727.         {   if( DrawLabels || (MonitList && DrawMonitDistance) )
  1728.             ReDrawFlag |= RFRefresh;
  1729.             SetFontSize((int)TokenValue);
  1730.         } else CommandError(ErrorMsg[ErrBigNum]);
  1731.         } else if( !CurToken )
  1732.         {   if( DrawLabels )
  1733.             ReDrawFlag |= RFRefresh;
  1734.         SetFontSize(8);
  1735.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1736.         break;
  1737.  
  1738.         case(WriteTok):
  1739.             FetchToken();
  1740.             if( !CurToken || (CurToken==FalseTok) )
  1741.             {   AllowWrite = False;
  1742.             } else if( CurToken == TrueTok )
  1743.             {   if( (FileDepth!=-1) && LineStack[FileDepth] )
  1744.                 {   CommandError(ErrorMsg[ErrInScrpt]);
  1745.                 } else AllowWrite = True;
  1746.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1747.             break;
  1748.  
  1749.     case(StereoTok):  
  1750.             FetchToken();
  1751.         if( !CurToken || (CurToken==TrueTok) )
  1752.             {   ReDrawFlag |= RFRefresh;
  1753.                 SetStereoMode(True);
  1754.             } else if( CurToken==FalseTok )
  1755.             {   ReDrawFlag |= RFRefresh;
  1756.                 SetStereoMode(False);
  1757.             } else CommandError(ErrorMsg[ErrSyntax]);
  1758.             break;
  1759.  
  1760.         case(PickingTok):
  1761.             switch( FetchToken() )
  1762.             {   case(TrueTok):     case(0):
  1763.                 case(IdentifyTok): SetPickMode(PickIdent); break;
  1764.                 case(FalseTok):
  1765.                 case(NoneTok):     SetPickMode(PickNone);  break;
  1766.                 case(LabelTok):    SetPickMode(PickLabel); break;
  1767.                 case(DistanceTok): SetPickMode(PickDist);  break;
  1768.                 case(AngleTok):    SetPickMode(PickAngle); break;
  1769.                 case(TorsionTok):  SetPickMode(PickTorsn); break;
  1770.                 case(MonitorTok):  SetPickMode(PickMonit); break;
  1771.                 case(CentreTok):   SetPickMode(PickCentr); break;
  1772.                 default:           CommandError(ErrorMsg[ErrBadOpt]);
  1773.             }
  1774.             break;
  1775.  
  1776.         case(BondTok):
  1777.         FetchToken();
  1778.         if( !CurToken || (CurToken==FalseTok) )
  1779.         {   ReDrawFlag |= RFRefresh;
  1780.         DrawDoubleBonds = False;
  1781.         } else if( CurToken == TrueTok )
  1782.         {   ReDrawFlag |= RFRefresh;
  1783.         DrawDoubleBonds = True;
  1784.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1785.         break;
  1786.  
  1787.         case(MonitorTok):
  1788.             FetchToken();
  1789.             if( !CurToken || (CurToken==TrueTok) )
  1790.             {   ReDrawFlag |= RFRefresh;
  1791.                 DrawMonitDistance = True;
  1792.             } else if( CurToken == FalseTok )
  1793.             {   ReDrawFlag |= RFRefresh;
  1794.                 DrawMonitDistance = False;
  1795.             } else CommandError(ErrorMsg[ErrBadOpt]);
  1796.             break;
  1797.  
  1798.         case(CartoonTok):
  1799.         FetchToken();
  1800.         if( !CurToken )
  1801.             {   ReDrawFlag |= RFRefresh;
  1802.                 DrawBetaArrows = True;
  1803.             CartoonHeight = 120;
  1804.             } else if( CurToken==TrueTok )
  1805.             {   ReDrawFlag |= RFRefresh;
  1806.                 DrawBetaArrows = True;
  1807.             } else if( CurToken==FalseTok )
  1808.             {   ReDrawFlag |= RFRefresh;
  1809.                 DrawBetaArrows = False;
  1810.         } else if( CurToken==NumberTok )
  1811.         {   if( *TokenPtr=='.' )
  1812.         {   TokenPtr++;
  1813.             FetchFloat(TokenValue,250);
  1814.         }
  1815.  
  1816.         if( TokenValue <= 500 )
  1817.                 {   CartoonHeight = (int)TokenValue;
  1818.                     ReDrawFlag |= RFRefresh;
  1819.         } else CommandError(ErrorMsg[ErrBigNum]);
  1820.         } else if( CurToken=='.' )
  1821.         {   FetchFloat(0,250);
  1822.         if( TokenValue <= 500 )
  1823.                 {   CartoonHeight = (int)TokenValue;
  1824.                     ReDrawFlag |= RFRefresh;
  1825.         } else CommandError(ErrorMsg[ErrBigNum]);
  1826.  
  1827.         } else CommandError(ErrorMsg[ErrBadOpt]);
  1828.         break;
  1829.  
  1830.     default:
  1831.         CommandError(ErrorMsg[ErrParam]);
  1832.     }
  1833. }
  1834.  
  1835.  
  1836. static void ExecuteColourCommand()
  1837. {
  1838.     register int flag;
  1839.  
  1840.     flag = 0;
  1841.     switch( FetchToken() )
  1842.     {   case(AtomTok):
  1843.         FetchToken();
  1844.     default:
  1845.         if( !CurToken )
  1846.         {   CommandError(ErrorMsg[ErrNoCol]);
  1847.         } else switch( CurToken )
  1848.         {   case(CPKTok):         CPKColourAttrib(); 
  1849.                       ReDrawFlag |= RFColour; break;
  1850.  
  1851.         case(AminoTok):       AminoColourAttrib();
  1852.                       ReDrawFlag |= RFColour; break;
  1853.  
  1854.         case(ShapelyTok):     ShapelyColourAttrib();
  1855.                       ReDrawFlag |= RFColour; break;
  1856.         
  1857.         case(UserTok):        UserMaskAttrib(MaskColourFlag);
  1858.                       ReDrawFlag |= RFColour; break;
  1859.  
  1860.         case(GroupTok):       ScaleColourAttrib(GroupAttr);
  1861.                       ReDrawFlag |= RFColour; break;
  1862.  
  1863.         case(ChainTok):       ScaleColourAttrib(ChainAttr);
  1864.                       ReDrawFlag |= RFColour; break;
  1865.  
  1866.         case(ChargeTok):      ScaleColourAttrib(ChargeAttr);
  1867.                       ReDrawFlag |= RFColour; break;
  1868.  
  1869.         case(TemperatureTok): ScaleColourAttrib(TempAttr);
  1870.                       ReDrawFlag |= RFColour; break;
  1871.  
  1872.         case(StructureTok):   StructColourAttrib();
  1873.                       ReDrawFlag |= RFColour; break;
  1874.  
  1875.         default:  if( ParseColour() )
  1876.               {   MonoColourAttrib(RVal,GVal,BVal);
  1877.                   ReDrawFlag |= RFColour;
  1878.               } else CommandError(ErrorMsg[ErrColour]);
  1879.         }
  1880.         break;
  1881.  
  1882.     case(BondTok):    
  1883.         case(DashTok):
  1884.         FetchToken();
  1885.         if( !CurToken )
  1886.         {   CommandError(ErrorMsg[ErrNoCol]);
  1887.         } else if( CurToken==NoneTok )
  1888.         {   ColourBondNone();
  1889.         ReDrawFlag |= RFColour;
  1890.         } else if( ParseColour() )
  1891.         {   ColourBondAttrib(RVal,GVal,BVal);
  1892.         ReDrawFlag |= RFColour;
  1893.         } else CommandError(ErrorMsg[ErrColour]);
  1894.         break;
  1895.  
  1896.     case(BackboneTok):
  1897.         FetchToken();
  1898.         if( !CurToken )
  1899.         {   CommandError(ErrorMsg[ErrNoCol]);
  1900.         } else if( CurToken==NoneTok )
  1901.         {   ColourBackNone();
  1902.         ReDrawFlag |= RFColour;
  1903.         } else if( ParseColour() )
  1904.         {   ColourBackAttrib(RVal,GVal,BVal);
  1905.         ReDrawFlag |= RFColour;
  1906.         } else CommandError(ErrorMsg[ErrColour]);
  1907.         break;
  1908.  
  1909.     case(SSBondTok):
  1910.         FetchToken();
  1911.         if( !CurToken )
  1912.         {   CommandError(ErrorMsg[ErrNoCol]);
  1913.         } else if( CurToken==NoneTok )
  1914.         {   ReDrawFlag |= RFColour;
  1915.         ColourHBondNone( False );
  1916.         } else if( ParseColour() )
  1917.         {   ReDrawFlag |= RFColour;
  1918.         ColourHBondAttrib(False,RVal,GVal,BVal);
  1919.         } else CommandError(ErrorMsg[ErrColour]);
  1920.         break;
  1921.  
  1922.     case(HBondTok):
  1923.         FetchToken();
  1924.         if( !CurToken )
  1925.         {   CommandError(ErrorMsg[ErrNoCol]);
  1926.         } else if( CurToken==NoneTok )
  1927.         {   ReDrawFlag |= RFColour;
  1928.         ColourHBondNone( True );
  1929.         } else if( CurToken==TypeTok )
  1930.         {   ReDrawFlag |= RFColour;
  1931.         ColourHBondType();
  1932.         } else if( ParseColour() )
  1933.         {   ReDrawFlag |= RFColour;
  1934.         ColourHBondAttrib(True,RVal,GVal,BVal);
  1935.         } else CommandError(ErrorMsg[ErrColour]);
  1936.         break;
  1937.  
  1938.     case(DotsTok):
  1939.         FetchToken();
  1940.         if( !CurToken )
  1941.         {   CommandError(ErrorMsg[ErrNoCol]);
  1942.         } else if( CurToken==PotentialTok )
  1943.         {   ReDrawFlag |= RFColour;
  1944.         ColourDotsPotential();
  1945.         } else if( ParseColour() )
  1946.         {   ReDrawFlag |= RFColour;
  1947.         ColourDotsAttrib(RVal,GVal,BVal);
  1948.         } else CommandError(ErrorMsg[ErrColour]);
  1949.         break;
  1950.  
  1951.         case(MonitorTok):
  1952.             FetchToken();
  1953.             if( !CurToken )
  1954.             {   CommandError(ErrorMsg[ErrNoCol]);
  1955.             } else if( CurToken == NoneTok )
  1956.             {   ColourMonitNone();
  1957.             } else if( ParseColour() )
  1958.             {   ReDrawFlag |= RFColour;
  1959.                 ColourMonitAttrib(RVal,GVal,BVal);
  1960.             } else CommandError(ErrorMsg[ErrColour]);
  1961.             break;
  1962.  
  1963.     case(AxesTok):
  1964.     case(BoundBoxTok):
  1965.     case(UnitCellTok):
  1966.         FetchToken();
  1967.         if( !CurToken )
  1968.         {   CommandError(ErrorMsg[ErrNoCol]);
  1969.         } else if( ParseColour() )
  1970.         {   BoxR = RVal;  BoxG = GVal;  BoxB = BVal;
  1971.         ReDrawFlag |= RFColour;
  1972.         } else CommandError(ErrorMsg[ErrColour]);
  1973.         break;
  1974.  
  1975.     case(LabelTok):
  1976.         FetchToken();
  1977.         if( !CurToken )
  1978.         {   CommandError(ErrorMsg[ErrNoCol]);
  1979.         } else if( CurToken==NoneTok )
  1980.         {   ReDrawFlag |= RFColour;
  1981.         UseLabelCol = False;
  1982.         } else if( ParseColour() )
  1983.         {   LabR = RVal;  LabG = GVal;  LabB = BVal;
  1984.         ReDrawFlag |= RFColour;
  1985.         UseLabelCol = True;
  1986.         } else CommandError(ErrorMsg[ErrColour]);
  1987.         break;
  1988.  
  1989.     case(TraceTok): 
  1990.         case(RibbonTok):
  1991.     case(CartoonTok):  flag = RibColBoth;     break;
  1992.     case(Ribbon1Tok):  flag = RibColInside;   break;
  1993.     case(Ribbon2Tok):  flag = RibColOutside;  break;
  1994.     }
  1995.  
  1996.     if( flag )
  1997.     {   FetchToken();
  1998.     if( !CurToken )
  1999.     {   CommandError(ErrorMsg[ErrNoCol]);
  2000.     } else if( CurToken==NoneTok )
  2001.     {   ReDrawFlag |= RFColour;
  2002.         ColourRibbonNone(flag);
  2003.     } else if( ParseColour() )
  2004.     {   ReDrawFlag |= RFColour;
  2005.         ColourRibbonAttrib(flag,RVal,GVal,BVal);
  2006.     } else CommandError(ErrorMsg[ErrColour]);
  2007.     }
  2008. }
  2009.  
  2010.  
  2011. static void ExecuteShowCommand()
  2012. {
  2013.     register Chain __far *chn;
  2014.     register Group __far *grp;
  2015.     register int chain,count;
  2016.     register Real temp;
  2017.     register char *str;
  2018.     char buffer[40];
  2019.  
  2020.     switch( FetchToken() )
  2021.     {   case(InfoTok):
  2022.         DescribeMolecule();
  2023.         break;
  2024.  
  2025.     case(SequenceTok):
  2026.         if( CommandActive )
  2027.             WriteChar('\n');
  2028.         CommandActive = False;
  2029.         if( !Database )
  2030.             return;
  2031.  
  2032.         for( chn=Database->clist; chn; chn=chn->cnext )
  2033.         {   chain = (InfoChainCount<2);  count = 0;
  2034.             for( grp=chn->glist; grp; grp=grp->gnext )
  2035.             if( grp->alist && !(grp->alist->flag&HeteroFlag) )
  2036.             {   if( !chain )
  2037.                 {   WriteString("Chain ");
  2038.                 WriteChar(chn->ident);
  2039.                 WriteString(":\n");
  2040.                 chain = True;
  2041.                 }
  2042.  
  2043.                 if( count == 10 )
  2044.                 {   WriteChar('\n');
  2045.                 count = 1;
  2046.                 } else count++;
  2047.  
  2048.                 str = Residue[grp->refno];
  2049.                 WriteChar(str[0]);
  2050.                 WriteChar(str[1]);
  2051.                 WriteChar(str[2]);
  2052.  
  2053.                 sprintf(buffer,"%-3d ",grp->serno);
  2054.                 WriteString(buffer);
  2055.             }
  2056.             WriteChar('\n');
  2057.         }
  2058.  
  2059.         WriteChar('\n');
  2060.         break;
  2061.  
  2062.     case(SymmetryTok):
  2063.         if( CommandActive )
  2064.             WriteChar('\n');
  2065.         CommandActive = False;
  2066.  
  2067.         if( *InfoSpaceGroup )
  2068.         {   sprintf(buffer,"Space Group ...... %s\n",InfoSpaceGroup);
  2069.             WriteString(buffer);
  2070.  
  2071.             sprintf(buffer,"Unit cell A ...... %g\n",InfoCellA);
  2072.             WriteString(buffer);
  2073.             sprintf(buffer,"Unit cell B ...... %g\n",InfoCellB);
  2074.             WriteString(buffer);
  2075.             sprintf(buffer,"Unit cell C ...... %g\n",InfoCellC);
  2076.             WriteString(buffer);
  2077.  
  2078.             temp = Rad2Deg*InfoCellAlpha;
  2079.             sprintf(buffer,"Unit cell alpha .. %g\n",temp);
  2080.             WriteString(buffer);
  2081.             temp = Rad2Deg*InfoCellBeta;
  2082.             sprintf(buffer,"Unit cell beta ... %g\n",temp);
  2083.             WriteString(buffer);
  2084.             temp = Rad2Deg*InfoCellGamma;
  2085.             sprintf(buffer,"Unit cell gamma .. %g\n",temp);
  2086.             WriteString(buffer);
  2087.  
  2088.         } else WriteString("No crystal symmetry data!\n");
  2089.         WriteChar('\n');
  2090.         break;
  2091.  
  2092.     default:
  2093.         CommandError(ErrorMsg[ErrBadArg]);
  2094.     }
  2095. }
  2096.  
  2097. void ZapDatabase()
  2098. {
  2099.     register int i;
  2100.  
  2101.     for( i=0; i<8; i++ )
  2102.     DialValue[i] = 0.0;
  2103.     SelectCount = 0;
  2104.  
  2105.     DestroyDatabase();
  2106.     ResetSymbolTable();
  2107.     ResetTransform();
  2108.     ResetRenderer();
  2109.     ResetRepres();
  2110.  
  2111.     ZoneBoth = True;
  2112.     HetaGroups = True;    
  2113.     Hydrogens = True;
  2114.  
  2115.     BackR = BackG = BackB = 0;
  2116. #ifndef IBMPC
  2117.     FBClear = False;
  2118. #endif
  2119.  
  2120.     ResetColourMap();
  2121.     DefineColourMap();
  2122.     ClearBuffers();
  2123.     TransferImage();
  2124.     ReDrawFlag = 0;
  2125.  
  2126.     if( Interactive )
  2127.     {   UpdateScrollBars();
  2128.     ClearImage();
  2129.     }
  2130.     AdviseUpdate(AdvName);
  2131.     AdviseUpdate(AdvClass);
  2132.     AdviseUpdate(AdvIdent);
  2133. }
  2134.  
  2135.  
  2136. static void WriteImageFile( name, type )
  2137.     char *name;  int type;
  2138. {
  2139.     if( !type )
  2140. #ifdef EIGHTBIT
  2141.     type = GIFTok;
  2142. #else
  2143.     type = PPMTok;
  2144. #endif
  2145.  
  2146.  
  2147.     switch( type )
  2148.     {   case(GIFTok):     WriteGIFFile(name);             break;
  2149.     case(BMPTok):     WriteBMPFile(name);             break;
  2150.     case(PPMTok):     WritePPMFile(name,True);        break;
  2151.     case(SUNTok):     WriteRastFile(name,False);      break;
  2152.     case(SUNRLETok):  WriteRastFile(name,True);       break;
  2153.     case(PICTTok):    WritePICTFile(name);            break;
  2154.     case(IRISTok):    WriteIRISFile(name);            break;
  2155.     case(EPSFTok):    WriteEPSFFile(name,True,True);  break;
  2156.     case(MonoPSTok):  WriteEPSFFile(name,False,True); break;
  2157.     case(VectPSTok):  WriteVectPSFile(name);          break;
  2158.  
  2159.     case(RasMolTok):
  2160.     case(ScriptTok):     WriteScriptFile(name);     break;
  2161.     case(POVRayTok):     WritePOVRayFile(name);     break;
  2162.     case(KinemageTok):   WriteKinemageFile(name);   break;
  2163.     case(MolScriptTok):  WriteMolScriptFile(name);  break;
  2164.     }
  2165. }
  2166.  
  2167.  
  2168. void ExecutePauseCommand()
  2169. {
  2170.     /* Ignore Pause Commands via IPC! */
  2171.     if( LineStack[FileDepth] )
  2172.     {   CommandActive = True;
  2173.         IsPaused = True;
  2174.  
  2175. #ifdef IBMPC
  2176.         /* Disable Drag & Drop! */
  2177.         DragAcceptFiles(CanvWin,FALSE);
  2178. #endif
  2179.     }
  2180. }
  2181.  
  2182. void ResumePauseCommand()
  2183. {
  2184.     register int ch,len;
  2185.     register FILE *fp;
  2186.  
  2187.     CommandActive = False;
  2188.     IsPaused = False;
  2189.  
  2190. #ifdef IBMPC
  2191.     /* Re-enable Drag & Drop! */
  2192.     DragAcceptFiles(CanvWin,TRUE);
  2193. #endif
  2194.  
  2195.     while( FileDepth >= 0 )
  2196.     {   fp = FileStack[FileDepth];
  2197.         do {
  2198.             len = 0;
  2199.             ch = getc(fp);
  2200.             while( (ch!='\n') && (ch!=EOF) )
  2201.             {   if( len<MAXBUFFLEN )
  2202.                     CurLine[len++] = ch;
  2203.                 ch = getc(fp);
  2204.             }
  2205.  
  2206.             LineStack[FileDepth]++;
  2207.             if( len<MAXBUFFLEN )
  2208.             {   CurLine[len] = '\0';
  2209.                 if( !ExecuteCommand() ) 
  2210.                 {   if( IsPaused ) 
  2211.                         return;
  2212.                 } else break;
  2213.             } else CommandError("Script command line too long");
  2214.         } while( ch!=EOF );
  2215.         free(NameStack[FileDepth]);
  2216.         fclose( fp );
  2217.         FileDepth--;
  2218.     }
  2219. }
  2220.  
  2221.  
  2222. static void ExecuteConnect( flag )
  2223.     int flag;
  2224. {
  2225.     register Bond __far *bptr;
  2226.     register int info;
  2227.  
  2228.     if( Database )
  2229.     {   ForEachBond
  2230.         if( bptr->col )
  2231.         Shade[Colour2Shade(bptr->col)].refcount--;
  2232.         info = (FileDepth == -1);
  2233.     CreateMoleculeBonds(info,flag);
  2234.     ReDrawFlag |= RFRefresh|RFColour;
  2235.         EnableWireframe(WireFlag,0);
  2236.     }
  2237. }
  2238.  
  2239. #ifdef IBMPC
  2240. /* Avoid Optimizer Warning */
  2241. #pragma optimize("g",off)
  2242. #endif
  2243.  
  2244.  
  2245. int ExecuteCommand()
  2246. {
  2247.     register char *param;
  2248.     register int option;
  2249.     register int i,done;
  2250.     register Long temp;
  2251.     FILE *script;
  2252.  
  2253.     TokenPtr = CurLine;
  2254.     if( !FetchToken() )
  2255.     {   TokenPtr = NULL;
  2256.     return( False );
  2257.     }
  2258.  
  2259.     switch( CurToken )
  2260.     {   case(LoadTok):    if( !Database )
  2261.               {   FetchToken();
  2262.                   option = FormatPDB;
  2263.                   if( !*TokenPtr || *TokenPtr==' ' )
  2264.                   {   if( IsMoleculeFormat(CurToken) )
  2265.                   {   option = Tok2Format(CurToken);
  2266.                                       FetchToken();
  2267.                   }
  2268.                   }
  2269.  
  2270.                   done = (FileDepth == -1);
  2271.                   if( !CurToken )
  2272.                   {   CommandError(ErrorMsg[ErrFilNam]);
  2273.                   break;
  2274.                               } else if( CurToken==InLineTok )
  2275.                               {   if( (FileDepth!=-1) && LineStack[FileDepth] )
  2276.                                   {   param = NameStack[FileDepth];
  2277.                                       FetchFile(option,done,param);
  2278.                                   } else CommandError(ErrorMsg[ErrOutScrpt]);
  2279.                   } else if( CurToken==StringTok )
  2280.                   {      FetchFile(option,done,TokenIdent);
  2281.                   } else FetchFile(option,done,TokenStart);
  2282.                   CurToken = 0;
  2283.  
  2284.                   if( Database )
  2285.                   {   ReDrawFlag |= RFRefresh | RFColour;
  2286.                   if( InfoBondCount < 1 )
  2287.                   {   EnableBackbone(CylinderFlag,80);
  2288.                   } else EnableWireframe(WireFlag,0);
  2289.                   CPKColourAttrib();
  2290.                   }
  2291.               } else CommandError(ErrorMsg[ErrBadLoad]);
  2292.               break;
  2293.  
  2294.     case(SelectTok):  FetchToken();
  2295.               if( !CurToken )
  2296.               {   option = NormAtomFlag;
  2297.                   if( HetaGroups ) option |= HeteroFlag;
  2298.                   if( Hydrogens )  option |= HydrogenFlag;
  2299.                   SelectZone(option);
  2300.               } else if( CurToken==AllTok )
  2301.               {   SelectZone(AllAtomFlag);
  2302.               } else if( CurToken==NoneTok )
  2303.               {   SelectZone(0x00);
  2304.               } else
  2305.                   if( (QueryExpr=ParseExpression(0)) )
  2306.                   {   if( !CurToken )
  2307.                   {   SelectZoneExpr(QueryExpr);
  2308.                   } else CommandError(ErrorMsg[ErrSyntax]);
  2309.                   DeAllocateExpr(QueryExpr);
  2310.                   }
  2311.               break;
  2312.  
  2313.     case(RestrictTok):
  2314.               FetchToken();
  2315.               if( !CurToken )
  2316.               {   option = NormAtomFlag;
  2317.                   if( HetaGroups ) option |= HeteroFlag;
  2318.                   if( Hydrogens )  option |= HydrogenFlag;
  2319.                   RestrictZone(option);
  2320.                   ReDrawFlag |= RFRefresh;
  2321.               } else if( CurToken==AllTok )
  2322.               {   RestrictZone(AllAtomFlag);
  2323.                   ReDrawFlag |= RFRefresh;
  2324.               } else if( CurToken==NoneTok )
  2325.               {   RestrictZone(0x00);
  2326.                   ReDrawFlag |= RFRefresh;
  2327.               } else
  2328.                   if( (QueryExpr=ParseExpression(0)) )
  2329.                   {   if( !CurToken )
  2330.                   {   RestrictZoneExpr(QueryExpr);
  2331.                       ReDrawFlag |= RFRefresh;
  2332.                   } else CommandError(ErrorMsg[ErrSyntax]);
  2333.                   DeAllocateExpr(QueryExpr);
  2334.                   } 
  2335.               break;
  2336.  
  2337.  
  2338.     case(ColourTok):  ExecuteColourCommand();
  2339.               break;
  2340.  
  2341.  
  2342.     case(WireframeTok):
  2343.               FetchToken();
  2344.               if( CurToken==FalseTok )
  2345.               {   ReDrawFlag |= RFRefresh;
  2346.                   DisableWireframe();
  2347.               } else if( (CurToken==TrueTok) || !CurToken )
  2348.               {   ReDrawFlag |= RFRefresh;
  2349.                   EnableWireframe(WireFlag,0);
  2350.                           } else if( CurToken==DashTok )
  2351.                           {   ReDrawFlag |= RFRefresh;
  2352.                               EnableWireframe(DashFlag,0);
  2353.               } else if( CurToken==NumberTok )
  2354.               {   if( *TokenPtr=='.' )
  2355.                   {   TokenPtr++;
  2356.                   FetchFloat(TokenValue,250);
  2357.                   }
  2358.  
  2359.                   if( TokenValue<500 )
  2360.                   {   EnableWireframe(CylinderFlag,
  2361.                                                   (int)TokenValue);
  2362.                   ReDrawFlag |= RFRefresh;
  2363.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2364.               } else if( CurToken=='.' )
  2365.               {   FetchFloat(0,250);
  2366.                   if( TokenValue<500 )
  2367.                   {   EnableWireframe(CylinderFlag,
  2368.                                                   (int)TokenValue);
  2369.                   ReDrawFlag |= RFRefresh;
  2370.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2371.               } else CommandError(ErrorMsg[ErrBadArg]);
  2372.               break;
  2373.  
  2374.     case(BackboneTok):
  2375.               FetchToken();
  2376.               if( CurToken==FalseTok )
  2377.               {   ReDrawFlag |= RFRefresh;
  2378.                   DisableBackbone();
  2379.               } else if( (CurToken==TrueTok) || !CurToken )
  2380.               {   ReDrawFlag |= RFRefresh;
  2381.                   EnableBackbone(WireFlag,0);
  2382.               } else if( CurToken==DashTok )
  2383.               {   ReDrawFlag |= RFRefresh;
  2384.                   EnableBackbone(DashFlag,0);
  2385.               } else if( CurToken==NumberTok )
  2386.               {   if( *TokenPtr=='.' )
  2387.                   {   TokenPtr++;
  2388.                   FetchFloat(TokenValue,250);
  2389.                   }
  2390.  
  2391.  
  2392.                   if( TokenValue<500 )
  2393.                   {   EnableBackbone(CylinderFlag,
  2394.                                                  (int)TokenValue);
  2395.                   ReDrawFlag |= RFRefresh;
  2396.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2397.               } else if( CurToken=='.' )
  2398.               {   FetchFloat(0,250);
  2399.                   if( TokenValue<500 )
  2400.                   {   EnableBackbone(CylinderFlag,
  2401.                                                  (int)TokenValue);
  2402.                   ReDrawFlag |= RFRefresh;
  2403.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2404.               } else CommandError(ErrorMsg[ErrBadArg]);
  2405.               break;
  2406.  
  2407.     case(CPKTok):
  2408.     case(SpacefillTok):
  2409.               FetchToken();
  2410.               if( CurToken==FalseTok )
  2411.               {   ReDrawFlag |= RFRefresh;
  2412.                   DisableSpacefill();
  2413.               } else if( CurToken==NumberTok )
  2414.               {   if( *TokenPtr=='.' )
  2415.                   {   TokenPtr++;
  2416.                   FetchFloat(TokenValue,250);
  2417.                   }
  2418.  
  2419.                   if( TokenValue<=500 )
  2420.                   {   SetRadiusValue(MaxFun((int)TokenValue,1));
  2421.                   ReDrawFlag |= RFRefresh;
  2422.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2423.               } else if( CurToken=='.' )
  2424.               {   FetchFloat(0,250);
  2425.                   if( TokenValue<=500 )
  2426.                   {   SetRadiusValue(MaxFun((int)TokenValue,1));
  2427.                   ReDrawFlag |= RFRefresh;
  2428.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2429.               } else if( CurToken==UserTok )
  2430.               {   UserMaskAttrib(MaskRadiusFlag);
  2431.                   ReDrawFlag |= RFRefresh;
  2432.               } else if( CurToken==TemperatureTok )
  2433.               {   ReDrawFlag |= RFRefresh;
  2434.                   SetRadiusTemperature();
  2435.               } else if( (CurToken==TrueTok) || !CurToken )
  2436.               {   ReDrawFlag |= RFRefresh;
  2437.                   SetVanWaalRadius();
  2438.               } else CommandError(ErrorMsg[ErrBadArg]);
  2439.               break;
  2440.  
  2441.     case(DashTok):    FetchToken();
  2442.               if( CurToken==FalseTok )
  2443.               {   ReDrawFlag |= RFRefresh;
  2444.                   DisableWireframe();
  2445.               } else if( (CurToken==TrueTok) || !CurToken )
  2446.               {   ReDrawFlag |= RFRefresh;
  2447.                   EnableWireframe(DashFlag,0);
  2448.               } else CommandError(ErrorMsg[ErrBadArg]);
  2449.               break;
  2450.  
  2451.     case(SSBondTok):  FetchToken();
  2452.               if( CurToken==NumberTok )
  2453.               {   if( *TokenPtr=='.' )
  2454.                   {   TokenPtr++;
  2455.                   FetchFloat(TokenValue,250);
  2456.                   }
  2457.  
  2458.                   if( TokenValue<=500 )
  2459.                   {   SetHBondStatus(False,True,(int)TokenValue);
  2460.                   ReDrawFlag |= RFRefresh;
  2461.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2462.               } else if( CurToken=='.' )
  2463.               {   FetchFloat(0,250);
  2464.                   if( TokenValue<=500 )
  2465.                   {   SetHBondStatus(False,True,(int)TokenValue);
  2466.                   ReDrawFlag |= RFRefresh;
  2467.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2468.               } else if( CurToken==FalseTok )
  2469.               {   ReDrawFlag |= RFRefresh;
  2470.                   SetHBondStatus(False,False,0);
  2471.               } else if( (CurToken==TrueTok) || !CurToken )
  2472.               {   ReDrawFlag |= RFRefresh;
  2473.                   SetHBondStatus(False,True,0);
  2474.               } else CommandError(ErrorMsg[ErrBadArg]);
  2475.               break;
  2476.  
  2477.     case(HBondTok):   FetchToken();
  2478.               if( CurToken==NumberTok )
  2479.               {   if( *TokenPtr=='.' )
  2480.                   {   TokenPtr++;
  2481.                   FetchFloat(TokenValue,250);
  2482.                   }
  2483.  
  2484.                   if( TokenValue<=500 )
  2485.                   {   SetHBondStatus(True,True,(int)TokenValue);
  2486.                   ReDrawFlag |= RFRefresh;
  2487.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2488.               } else if( CurToken=='.' )
  2489.               {   FetchFloat(0,250);
  2490.                   if( TokenValue<=500 )
  2491.                   {   SetHBondStatus(True,True,(int)TokenValue);
  2492.                   ReDrawFlag |= RFRefresh;
  2493.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2494.               } else if( CurToken==FalseTok )
  2495.               {   ReDrawFlag |= RFRefresh;
  2496.                   SetHBondStatus(True,False,0);
  2497.               } else if( (CurToken==TrueTok) || !CurToken )
  2498.               {   ReDrawFlag |= RFRefresh;
  2499.                   SetHBondStatus(True,True,0);
  2500.               } else CommandError(ErrorMsg[ErrBadArg]);
  2501.               break;
  2502.  
  2503.     case(RibbonTok):  FetchToken();
  2504.               if( CurToken==NumberTok )
  2505.               {   if( *TokenPtr=='.' )
  2506.                   {   TokenPtr++;
  2507.                   FetchFloat(TokenValue,250);
  2508.                   }
  2509.  
  2510.                   if( TokenValue<=1000 )
  2511.                   {   SetRibbonStatus(True,RibbonFlag,
  2512.                           (int)TokenValue);
  2513.                   ReDrawFlag |= RFRefresh;
  2514.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2515.               } else if( CurToken=='.' )
  2516.               {   FetchFloat(0,250);
  2517.                   if( TokenValue<=1000 )
  2518.                   {   SetRibbonStatus(True,RibbonFlag,
  2519.                           (int)TokenValue);
  2520.                   ReDrawFlag |= RFRefresh;
  2521.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2522.               } else if( CurToken==FalseTok )
  2523.               {   ReDrawFlag |= RFRefresh;
  2524.                   SetRibbonStatus(False,RibbonFlag,0);
  2525.               } else if( (CurToken==TrueTok) || !CurToken )
  2526.               {   ReDrawFlag |= RFRefresh;
  2527.                   SetRibbonStatus(True,RibbonFlag,0);
  2528.               } else CommandError(ErrorMsg[ErrBadArg]);
  2529.               break;
  2530.  
  2531.     case(StrandsTok): FetchToken();
  2532.                           if( CurToken == DashTok )
  2533.                           {   option = DashStrandFlag;
  2534.                               FetchToken();
  2535.                           } else option = StrandFlag;
  2536.  
  2537.               if( CurToken==NumberTok )
  2538.               {   if( *TokenPtr=='.' )
  2539.                   {   TokenPtr++;
  2540.                   FetchFloat(TokenValue,250);
  2541.                   }
  2542.  
  2543.                   if( TokenValue<=1000 )
  2544.                   {   SetRibbonStatus(True,option,(int)TokenValue);
  2545.                   ReDrawFlag |= RFRefresh;
  2546.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2547.               } else if( CurToken=='.' )
  2548.               {   FetchFloat(0,250);
  2549.                   if( TokenValue<=1000 )
  2550.                   {   SetRibbonStatus(True,option,(int)TokenValue);
  2551.                   ReDrawFlag |= RFRefresh;
  2552.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2553.               } else if( CurToken==FalseTok )
  2554.               {   ReDrawFlag |= RFRefresh;
  2555.                   SetRibbonStatus(False,option,0);
  2556.               } else if( (CurToken==TrueTok) || !CurToken )
  2557.               {   ReDrawFlag |= RFRefresh;
  2558.                   SetRibbonStatus(True,option,0);
  2559.               } else CommandError(ErrorMsg[ErrBadArg]);
  2560.               break;
  2561.  
  2562.     case(TraceTok):   FetchToken();
  2563.                           if( CurToken==FalseTok )
  2564.                           {   ReDrawFlag |= RFRefresh;
  2565.                               SetRibbonStatus(False,TraceFlag,80);
  2566.                           } else if( (CurToken==TrueTok) || !CurToken )
  2567.                           {   ReDrawFlag |= RFRefresh;
  2568.                               SetRibbonStatus(True,TraceFlag,80);
  2569.                           } else if( CurToken==NumberTok )
  2570.                           {   if( *TokenPtr=='.' )
  2571.                               {   TokenPtr++;
  2572.                                   FetchFloat(TokenValue,250);
  2573.                               }
  2574.  
  2575.                               if( TokenValue<500 )
  2576.                               {   SetRibbonStatus(True,TraceFlag,
  2577.                                                  (int)TokenValue);
  2578.                                   ReDrawFlag |= RFRefresh;
  2579.                               } else CommandError(ErrorMsg[ErrBigNum]);
  2580.                           } else if( CurToken=='.' )
  2581.                           {   FetchFloat(0,250);
  2582.                               if( TokenValue<500 )
  2583.                               {   SetRibbonStatus(True,TraceFlag,
  2584.                                                  (int)TokenValue);
  2585.                                   ReDrawFlag |= RFRefresh;
  2586.                               } else CommandError(ErrorMsg[ErrBigNum]);
  2587.                           } else CommandError(ErrorMsg[ErrBadArg]);
  2588.                           break;
  2589.  
  2590.     case(CartoonTok): FetchToken();
  2591.               if( CurToken==NumberTok )
  2592.               {   if( *TokenPtr=='.' )
  2593.                   {   TokenPtr++;
  2594.                   FetchFloat(TokenValue,250);
  2595.                   }
  2596.  
  2597.                   if( TokenValue<=1000 )
  2598.                   {   SetRibbonStatus(True,CartoonFlag,
  2599.                           (int)TokenValue);
  2600.                   ReDrawFlag |= RFRefresh;
  2601.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2602.               } else if( CurToken=='.' )
  2603.               {   FetchFloat(0,250);
  2604.                   if( TokenValue<=1000 )
  2605.                   {   SetRibbonStatus(True,CartoonFlag,
  2606.                           (int)TokenValue);
  2607.                   ReDrawFlag |= RFRefresh;
  2608.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2609.               } else if( CurToken==FalseTok )
  2610.               {   ReDrawFlag |= RFRefresh;
  2611.                   SetRibbonStatus(False,CartoonFlag,0);
  2612.               } else if( (CurToken==TrueTok) || !CurToken )
  2613.               {   ReDrawFlag |= RFRefresh;
  2614.                   SetRibbonStatus(True,CartoonFlag,0);
  2615.               } else CommandError(ErrorMsg[ErrBadArg]);
  2616.               break;
  2617.  
  2618.     case(DotsTok):    FetchToken();
  2619.               if( CurToken==NumberTok )
  2620.               {   if( TokenValue<=1000 )
  2621.                   {   if( TokenValue )
  2622.                   {   CalculateSurface((int)TokenValue);
  2623.                   } else CalculateSurface(1);
  2624.                   ReDrawFlag |= RFRefresh;
  2625.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2626.               } else if( CurToken==FalseTok )
  2627.               {   ReDrawFlag |= RFRefresh;
  2628.                   DeleteSurface();
  2629.               } else if( (CurToken==TrueTok) || !CurToken )
  2630.               {   ReDrawFlag |= RFRefresh;
  2631.                   CalculateSurface(100);
  2632.               } else CommandError(ErrorMsg[ErrBadArg]);
  2633.               break;
  2634.  
  2635.         case(MonitorTok): FetchToken();
  2636.                           if( CurToken == NumberTok )
  2637.                           {   temp = TokenValue;
  2638.                               FetchToken();
  2639.                               if( CurToken == ',' )
  2640.                                   FetchToken();
  2641.  
  2642.                               if( CurToken == NumberTok )
  2643.                               {   CreateMonitor(temp,TokenValue);
  2644.                                   ReDrawFlag |= RFRefresh;
  2645.                               } else CommandError(ErrorMsg[ErrNotNum]);
  2646.                           } else if( CurToken == FalseTok )
  2647.                           {   ReDrawFlag |= RFRefresh;
  2648.                               DeleteMonitors();
  2649.                           } else CommandError(ErrorMsg[ErrBadArg]);
  2650.                           break;
  2651.  
  2652.     case(SlabTok):    FetchToken();
  2653.               if( (CurToken==NumberTok) || (CurToken=='.') )
  2654.               {   if( CurToken==NumberTok )
  2655.                   {   if( *TokenPtr=='.' )
  2656.                   {   TokenPtr++;
  2657.                       FetchFloat(TokenValue,100);
  2658.                   } else TokenValue *= 100;
  2659.                   } else FetchFloat(0,100);
  2660.  
  2661.                   if( TokenValue<=10000 )
  2662.                   {   DialValue[7] = (TokenValue-5000)/5000.0;
  2663.                   /* UpdateScrollBars(); */
  2664.                   ReDrawFlag |= RFSlab;
  2665.                   UseSlabPlane = True;
  2666.                   UseShadow = False;
  2667.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2668.  
  2669.               } else if( CurToken==FalseTok )
  2670.               {   if( UseSlabPlane )
  2671.                   {   ReDrawFlag |= RFRefresh;
  2672.                   UseSlabPlane = False;
  2673.                   }
  2674.               } else if( !CurToken || (CurToken==TrueTok) )
  2675.               {   if( !UseSlabPlane )
  2676.                   {   ReDrawFlag |= RFRefresh;
  2677.                   UseSlabPlane = True;
  2678.                   UseShadow = False;
  2679.                   }
  2680.               } else CommandError(ErrorMsg[ErrSyntax]);
  2681.               break;
  2682.  
  2683.     case(ZoomTok):    FetchToken();
  2684.               if( (CurToken==NumberTok) || (CurToken=='.') )
  2685.               {   if( CurToken==NumberTok )
  2686.                   {   if( *TokenPtr=='.' )
  2687.                   {   TokenPtr++;
  2688.                       FetchFloat(TokenValue,100);
  2689.                   } else TokenValue *= 100;
  2690.                   } else FetchFloat(0,100);
  2691.  
  2692.                   if( TokenValue<=10000 )
  2693.                   {   DialValue[3] = (TokenValue-10000)/10000.0;
  2694.                   ReDrawFlag |= RFZoom;
  2695.                   } else if( Database )
  2696.                   {   /* Magnification */
  2697.                   TokenValue -= 10000;
  2698.                   temp = (Long)(MaxZoom*10000);
  2699.                   if( TokenValue<=temp )
  2700.                   {   DialValue[3] = (Real)TokenValue/temp;
  2701.                       ReDrawFlag |= RFZoom;
  2702.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2703.                   }
  2704.               } else if( CurToken==TrueTok )
  2705.               {   ReDrawFlag |= RFZoom;
  2706.                   DialValue[3] = 0.5;
  2707.               } else if( !CurToken || (CurToken==FalseTok) )
  2708.               {   ReDrawFlag |= RFZoom;
  2709.                   DialValue[3] = 0.0;
  2710.               } else CommandError(ErrorMsg[ErrSyntax]);
  2711.               /* UpdateScrollBars(); */
  2712.               break;
  2713.  
  2714.     case(RotateTok):  FetchToken();
  2715.               if( CurToken==XTok )
  2716.               {   option = 0;
  2717.               } else if( CurToken==YTok )
  2718.               {   option = 1;
  2719.               } else if( CurToken==ZTok )
  2720.               {   option = 2;
  2721.               } else
  2722.               {   CommandError(ErrorMsg[ErrSyntax]);
  2723.                   break;
  2724.               }
  2725.  
  2726.               FetchToken();
  2727.               if( (done=(CurToken=='-')) )
  2728.                   FetchToken();
  2729. #ifdef INVERT
  2730.               if( option != 1 )
  2731.                   done = !done;
  2732. #endif
  2733.               if( (CurToken==NumberTok) || (CurToken=='.') )
  2734.               {   if( CurToken==NumberTok )
  2735.                   {   if( *TokenPtr=='.' )
  2736.                   {   TokenPtr++;
  2737.                       FetchFloat(TokenValue,100);
  2738.                   } else TokenValue *= 100;
  2739.                   } else FetchFloat(0,100);
  2740.  
  2741.                   if( TokenValue )
  2742.                   {   if( ReDrawFlag & RFRotate )
  2743.                       PrepareTransform();
  2744.  
  2745.                   ReDrawFlag |= (1<<option);
  2746.                   if( done ) TokenValue = -TokenValue;
  2747.                   DialValue[option] += TokenValue/18000.0;
  2748.  
  2749.                   while( DialValue[option]<-1.0 )
  2750.                       DialValue[option] += 2.0;
  2751.                   while( DialValue[option]>1.0 )
  2752.                       DialValue[option] -= 2.0;
  2753.                   if( Interactive )
  2754.                       UpdateScrollBars();
  2755.                   }
  2756.               } else CommandError(ErrorMsg[ErrNotNum]);
  2757.               break;
  2758.  
  2759.     case(TranslateTok):
  2760.               FetchToken();
  2761.               if( CurToken==XTok )
  2762.               {   option = 4;
  2763.               } else if( CurToken==YTok )
  2764.               {   option = 5;
  2765.               } else if( CurToken==ZTok )
  2766.               {   option = 6;
  2767.               } else
  2768.               {   CommandError(ErrorMsg[ErrSyntax]);
  2769.                   break;
  2770.               }
  2771.  
  2772.               FetchToken();
  2773.               if( (done=(CurToken=='-')) )
  2774.                   FetchToken();
  2775. #ifdef INVERT
  2776.               if( option == 5 )
  2777.                   done = !done;
  2778. #endif
  2779.  
  2780.               if( (CurToken==NumberTok) || (CurToken=='.') )
  2781.               {   if( CurToken==NumberTok )
  2782.                   {   if( *TokenPtr=='.' )
  2783.                   {   TokenPtr++;
  2784.                       FetchFloat(TokenValue,100);
  2785.                   } else TokenValue *= 100;
  2786.                   } else FetchFloat(0,100);
  2787.  
  2788.                   if( TokenValue<=10000 )
  2789.                   {   ReDrawFlag |= (1<<option);
  2790.                   if( done ) TokenValue = -TokenValue;
  2791.                   DialValue[option] = TokenValue/10000.0;
  2792.                   /* UpdateScrollBars(); */
  2793.                   } else CommandError(ErrorMsg[ErrBigNum]);
  2794.               } else CommandError(ErrorMsg[ErrNotNum]);
  2795.               break;
  2796.  
  2797.     case(StereoTok):  FetchToken();
  2798.               if( !CurToken || (CurToken==TrueTok) )
  2799.               {   ReDrawFlag |= RFRefresh;
  2800.                   SetStereoMode(True);
  2801.               } else if( CurToken==FalseTok )
  2802.               {   ReDrawFlag |= RFRefresh;
  2803.                   SetStereoMode(False);
  2804.               } else CommandError(ErrorMsg[ErrSyntax]);
  2805.               break;
  2806.  
  2807.     case(CentreTok):  FetchToken();
  2808.               if( !CurToken || (CurToken==AllTok) )
  2809.               {   CenX = CenY = CenZ = 0;
  2810.               } else
  2811.                   if( (QueryExpr=ParseExpression(0)) )
  2812.                   {   if( !CurToken )
  2813.                   {   CentreZoneExpr(QueryExpr);
  2814.                   } else CommandError(ErrorMsg[ErrSyntax]);
  2815.                   DeAllocateExpr(QueryExpr);
  2816.                   }
  2817.               break;
  2818.  
  2819.     case(ResizeTok):  FetchToken();
  2820.               break;
  2821.  
  2822.     case(ResetTok):   for( i=0; i<8; i++ )
  2823.                   DialValue[i] = 0.0;
  2824.               ReDrawFlag |= RFDials;
  2825.               ResetTransform();
  2826.  
  2827.               /* ReDrawFlag |= RFRefresh|RFColour; */
  2828.               /* DisplayMode = 0;                  */
  2829.  
  2830.               if( Interactive )
  2831.                   UpdateScrollBars();
  2832.               break;
  2833.  
  2834.     case('?'):
  2835.     case(HelpTok):    if( !HelpFileName )
  2836.                   InitHelpFile();
  2837.               if( HelpInfo )
  2838.                   FindHelpInfo();
  2839.               CurToken=0;
  2840.               break;
  2841.  
  2842.     case(SetTok):     ExecuteSetCommand();
  2843.               break;
  2844.  
  2845.     case(LabelTok):   FetchToken();
  2846.               if( !CurToken || (CurToken==TrueTok) )
  2847.               {   if( InfoChainCount>1 )
  2848.                   {   DefineLabels("%n%r:%c.%a");
  2849.                   } else if( MainGroupCount>1 )
  2850.                   {   DefineLabels("%n%r.%a");
  2851.                   } else DefineLabels("%e%i");
  2852.               } else if( CurToken==FalseTok )
  2853.               {   DeleteLabels();
  2854.               } else if( CurToken!=StringTok )
  2855.               {   DefineLabels(TokenStart);
  2856.                               CurToken = 0;
  2857.               } else DefineLabels(TokenIdent);
  2858.               ReDrawFlag |= RFRefresh;
  2859.               break;
  2860.  
  2861.     case(EchoTok):    FetchToken();
  2862.               if( CommandActive )
  2863.                   WriteChar('\n');
  2864.               CommandActive = False;
  2865.  
  2866.               if( CurToken==StringTok )
  2867.               {   WriteString(TokenIdent);
  2868.               } else if( CurToken )
  2869.                   WriteString(TokenStart);
  2870.               WriteChar('\n');
  2871.               CurToken = 0;
  2872.               break;
  2873.  
  2874.         case(WaitTok):    if( (FileDepth!=-1) && LineStack[FileDepth] )
  2875.                           {   ExecutePauseCommand();
  2876.                           } else CommandError(ErrorMsg[ErrOutScrpt]);
  2877.                           break;
  2878.  
  2879.     case(DefineTok):  FetchToken();
  2880.               if( CurToken != IdentTok ) 
  2881.               {   CommandError(ErrorMsg[ErrSetName]);
  2882.                   break;
  2883.               }
  2884.  
  2885.               if( (param = (char*)malloc(TokenLength+1)) )
  2886.               {   for( i=0; i<=TokenLength; i++ )
  2887.                   param[i] = TokenIdent[i];
  2888.  
  2889.                   if( FetchToken() )
  2890.                   {   if( (QueryExpr=ParseExpression(0)) )
  2891.                   {   done = DefineSetExpr(param,QueryExpr);
  2892.                   } else done = True;
  2893.                   } else done = DefineSetExpr(param,(Expr*)NULL);
  2894.               } else done = False;
  2895.  
  2896.               if( !done )
  2897.                   CommandError(ErrorMsg[ErrBadSet]);
  2898.               break;
  2899.  
  2900.     case(BackgroundTok):
  2901.               FetchToken();
  2902.               if( !CurToken )
  2903.               {   CommandError(ErrorMsg[ErrNoCol]);
  2904.               } else if( ParseColour() )
  2905.               {   ReDrawFlag |= RFColour;
  2906.                   BackR = RVal;
  2907.                   BackG = GVal;
  2908.                   BackB = BVal;
  2909. #ifndef IBMPC
  2910.                   FBClear = False;
  2911. #endif
  2912.               } else if( CurToken )
  2913.                   CommandError(ErrorMsg[ErrColour]);
  2914.               break;
  2915.  
  2916.     case(WriteTok):
  2917.     case(SaveTok):    i = CurToken; /* Save keyword! */
  2918.               if( !AllowWrite )
  2919.                               if( (FileDepth!=-1) && LineStack[FileDepth] )
  2920.                   {   CommandError(ErrorMsg[ErrInScrpt]);
  2921.                       break;
  2922.                   }
  2923.  
  2924.               option = FetchToken();
  2925.               if( (option==RasMolTok) || (option==ScriptTok)
  2926.                   || IsMoleculeFormat(option)
  2927.                   || IsImageFormat(option) )
  2928.               {   if( !*TokenPtr || *TokenPtr==' ' )
  2929.                   FetchToken();
  2930.               } else if( i==SaveTok )
  2931.               {   option = PDBTok;
  2932.               } else option = 0;
  2933.  
  2934.               if( !CurToken )
  2935.               {   CommandError(ErrorMsg[ErrFilNam]);
  2936.                   break;
  2937.               } else if( CurToken==StringTok )
  2938.               {      ProcessFileName(TokenIdent);
  2939.               } else ProcessFileName(TokenStart);
  2940.               param = DataFileName;
  2941.               CurToken = 0;
  2942.  
  2943.               if( !IsMoleculeFormat(option) )
  2944.               {   if( ReDrawFlag ) RefreshScreen();
  2945.                   WriteImageFile( param, option );
  2946.  
  2947.               } else switch(option)
  2948.               {   case(NMRPDBTok):
  2949.                               case(PDBTok):  SavePDBMolecule(param); break;
  2950.                               case(MDLTok):  SaveMDLMolecule(param); break;
  2951.                   case(XYZTok):  SaveXYZMolecule(param); break;
  2952.                   case(CIFTok):  SaveCIFMolecule(param); break;
  2953. #ifdef CEXIOLIB
  2954.                               case(CEXTok):  SaveCEXMolecule(param); break;
  2955. #endif
  2956.                   case(AlchemyTok): SaveAlchemyMolecule(param);
  2957.                         break;
  2958.               } break;
  2959.  
  2960.     case(SourceTok):
  2961.     case(ScriptTok):  FetchToken();
  2962.               if( FileDepth<STACKSIZE )
  2963.               {   if( !CurToken )
  2964.                   {   CommandError(ErrorMsg[ErrFilNam]);
  2965.                   break;
  2966.                   } else if( CurToken==StringTok )
  2967.                   {      ProcessFileName(TokenIdent);
  2968.                   } else ProcessFileName(TokenStart);
  2969.                   CurToken = 0;
  2970.  
  2971.                   script = fopen(DataFileName,"r");
  2972.                   LoadScriptFile(script,DataFileName);
  2973.               } else CommandError(ErrorMsg[ErrScript]);
  2974.               break;
  2975.  
  2976.     case(PrintTok):   if( !PrintImage() )
  2977.               {   if( CommandActive )
  2978.                   WriteChar('\n');
  2979.                   WriteString("Warning: No suitable printer!\n");
  2980.                   CommandActive = False;
  2981.               }
  2982.               break;
  2983.  
  2984.     case(ClipboardTok):
  2985.               if( !ClipboardImage() )
  2986.               {   if( CommandActive )
  2987.                   WriteChar('\n');
  2988.                   WriteString("Unable to copy to clipboard!\n");
  2989.                   CommandActive = False;
  2990.               }
  2991.               break;
  2992.  
  2993.     case(RenumTok):   FetchToken();
  2994.               if( CurToken )
  2995.               {   if( (done = (CurToken=='-')) )
  2996.                   FetchToken();
  2997.  
  2998.                   if( CurToken==NumberTok )
  2999.                   {   if( done )
  3000.                   {     RenumberMolecule(-(int)TokenValue);
  3001.                   } else RenumberMolecule((int)TokenValue); 
  3002.                   } else CommandError(ErrorMsg[ErrNotNum]);
  3003.               } else RenumberMolecule(1);
  3004.               break;
  3005.  
  3006.     case(StructureTok):
  3007.                           FetchToken();
  3008.                           if( !CurToken || (CurToken==FalseTok) )
  3009.               {   DetermineStructure(False);
  3010.                           } else if( CurToken==TrueTok )
  3011.                           {   DetermineStructure(True);
  3012.                           } else CommandError(ErrorMsg[ErrSyntax]);
  3013.               break;
  3014.  
  3015.     case(ConnectTok): FetchToken();
  3016.                           if( !CurToken )
  3017.                           {   if( MainAtomCount+HetaAtomCount > 255 )
  3018.                               {   ExecuteConnect(False);
  3019.                               } else ExecuteConnect(True);
  3020.                           } else if( CurToken==TrueTok )
  3021.                           {   ExecuteConnect(True);
  3022.                           } else if( CurToken==FalseTok )
  3023.                           {   ExecuteConnect(False);
  3024.               } else CommandError(ErrorMsg[ErrSyntax]);
  3025.               break;
  3026.  
  3027.         case(RefreshTok): if( ReDrawFlag )
  3028.                               RefreshScreen();
  3029.                           break;
  3030.  
  3031.     case(ShowTok):    ExecuteShowCommand();
  3032.               break;
  3033.  
  3034.     case(ZapTok):     ZapDatabase();
  3035.               break;
  3036.  
  3037.     case(QuitTok):    return( True );
  3038.     default:          CommandError("Unrecognised command");
  3039.               break;
  3040.     }
  3041.  
  3042.     if( CurToken )
  3043.     if( FetchToken() )
  3044.         CommandError("Warning: Ignoring rest of command");
  3045.     TokenPtr = NULL;
  3046.     return( False );
  3047. }
  3048.  
  3049. #ifdef IBMPC
  3050. /* Avoid Optimizer Warning! */
  3051. #pragma optimize("g",)
  3052. #endif
  3053.  
  3054.  
  3055. int ExecuteIPCCommand( ptr )
  3056.     char __huge *ptr;
  3057. {
  3058.     register char *src,*dst;
  3059.     register int len,depth;
  3060.     register int result;
  3061.     auto char buffer[256];
  3062.  
  3063.  
  3064.     /* Ignore IPC commands while paused! */
  3065.     if( IsPaused ) return( 0 );
  3066.  
  3067.     result = 0;
  3068.     FileDepth = 0;
  3069.     *LineStack = 0;
  3070. #ifdef IBMPC
  3071.     *NameStack = "DDE Error";
  3072. #else
  3073.     *NameStack = "IPC Error";
  3074. #endif
  3075.  
  3076.     /* Save command line */
  3077.     src=CurLine;  dst=buffer;
  3078.     while( (*dst++ = *src++) );
  3079.    
  3080.     while( *ptr && (*ptr==' ') )
  3081.     ptr++;
  3082.  
  3083.     if( *ptr=='[' )
  3084.     {   depth = 0;
  3085.     while( *ptr++ == '[' )
  3086.     {   dst = CurLine;
  3087.         depth=0;  len=1;
  3088.  
  3089.     
  3090.         do {
  3091.         if( *ptr==']' )
  3092.         {   if( !depth )
  3093.             {   *dst = '\0';
  3094.             ptr++; break;
  3095.             } else depth--;
  3096.         } else if( *ptr=='[' )
  3097.             depth++;
  3098.  
  3099.         if( len<255 )
  3100.         {   *dst++ = *ptr;
  3101.             len++;
  3102.         }
  3103.         } while( *ptr++ );
  3104.  
  3105.         if( len==255 )
  3106.         {   if( CommandActive )
  3107.             WriteChar('\n');
  3108.         WriteString("Warning: Remote command too long!\n");
  3109.         CommandActive = False;
  3110.         } else if( ExecuteCommand() )
  3111.         result = 2;
  3112.  
  3113.         while( *ptr && ((*ptr==' ')||(*ptr==';')) )
  3114.         ptr++;
  3115.     }
  3116.     } else if( *ptr )
  3117.     {   dst = CurLine;
  3118.     len = 0;
  3119.  
  3120.     while( True )
  3121.     {   if( len==255 )
  3122.         {   if( CommandActive )
  3123.             WriteChar('\n');
  3124.         WriteString("Warning: Remote command too long!\n");
  3125.         CommandActive = False;
  3126.         break;
  3127.         }
  3128.  
  3129.         if( !(*dst++ = *ptr++) )
  3130.         {   if( ExecuteCommand() )
  3131.             result = 2;
  3132.         break;
  3133.         } else len++;
  3134.     }
  3135.     }
  3136.  
  3137.     FileDepth = -1;
  3138.     if( CommandActive )
  3139.     {   src=buffer; dst=CurLine;
  3140.     while( (*dst++ = *src++) );
  3141.     if( !result ) result = 1;
  3142.     }
  3143.  
  3144.     return( result );
  3145. }
  3146.  
  3147.  
  3148. void InitialiseCommand()
  3149. {
  3150.     MaxHist = MinHist = 1;
  3151.     HistBuff[0] = 0;
  3152.  
  3153.     HelpFileName = NULL;
  3154.     FreeInfo = (void __far*)0;
  3155.     HelpInfo = (void __far*)0;
  3156.  
  3157.     CommandActive = False;
  3158.     SelectCount = 0;
  3159.     TokenPtr = NULL;
  3160.     FileDepth = -1;
  3161.  
  3162.     AllowWrite = False;
  3163.     IsPaused = False;
  3164. }
  3165.