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

  1. /* rasmol.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, August 1995
  4.  * Version 2.6
  5.  */
  6.  
  7. #ifndef sun386
  8. #include <stdlib.h>
  9. #endif
  10. #include <signal.h>
  11. #include <stdio.h>
  12. #include <math.h>
  13.  
  14. #define RASMOL
  15. #include "rasmol.h"
  16. #include "graphics.h"
  17. #include "molecule.h"
  18. #include "infile.h"
  19. #include "abstree.h"
  20. #include "transfor.h"
  21. #include "command.h"
  22. #include "render.h"
  23. #include "repres.h"
  24. #include "pixutils.h"
  25. #include "outfile.h"
  26.  
  27. #ifdef TERMIOS
  28. #include <sys/types.h>
  29. #include <sys/time.h>
  30.  
  31. #ifdef NEXT
  32. #define __FreeBSD__
  33. #endif
  34.  
  35. #ifdef esv
  36. #include <sysv/sys/termio.h>
  37. #else
  38. #ifdef __FreeBSD__
  39. #include <sys/ioctl.h>
  40. #include <sys/termios.h>
  41. #define TCSETAW TIOCSETAW
  42. #define TCGETA  TIOCGETA
  43. #else
  44. #ifdef _CONVEX_SOURCE
  45. #include <sys/ioctl.h>
  46. #include "/usr/sys/base/h/ioctl.h"
  47. #define TCSETAW TIOCSETAW
  48. #define TCGETA  TIOCGETA
  49. #else
  50. #include <sys/termio.h>
  51. #endif /* _CONVEX_SOURCE */
  52. #endif /* __FreeBSD__ */
  53. #endif /* esv */
  54.  
  55. #ifdef esv
  56. #include <sysv/unistd.h>
  57. #else
  58. #include <unistd.h>
  59. #endif
  60.  
  61. #if defined(_SEQUENT_) || defined(_AIX)
  62. #include <sys/select.h>
  63. #endif
  64.  
  65. #ifdef __sgi
  66. /* Avoid 'bzero' Compiler Warnings! */
  67. #include <bstring.h>
  68. #endif
  69. #endif /* TERMIOS */
  70.  
  71. #ifdef VMS
  72. #include <tt2def.h>
  73. #include <iodef.h>
  74. #include <starlet.h>
  75. #include <string.h>
  76. #include <time.h>
  77. #endif
  78.  
  79. #ifdef SOCKETS
  80. #include <sys/socket.h>
  81. #include <netinet/in.h>
  82. #include <netdb.h>
  83. #endif
  84.  
  85. #define TwoPi    6.2832
  86.  
  87.  
  88. #ifdef VMS
  89. static struct {
  90.         unsigned short size; 
  91.         unsigned short type;
  92.         char *string;
  93.         } StdInDesc = { 10, 0, "SYS$INPUT:" };
  94.  
  95. /* Character Terminator Mask! */
  96. static int StdInMask[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  97.  
  98. static short StdInBlck[4];
  99. static int StdInMode[3];
  100. static int StdInOrig[3];
  101. static short StdInChan;
  102. static int StdInStatus;
  103. static char StdInChar;
  104. static int StdInFlag;
  105. #endif
  106.  
  107. #ifdef TERMIOS
  108. #ifdef __FreeBSD__
  109. static struct termios OrigTerm;
  110. static struct termios IntrTerm;
  111. #else
  112. static struct termio OrigTerm;
  113. static struct termio IntrTerm;
  114. #endif
  115.  
  116. static struct fd_set OrigWaitSet;
  117. static struct fd_set WaitSet;
  118. static struct timeval TimeOut;
  119. static int WaitWidth;
  120. static int FileNo;
  121.  
  122. #ifdef SOCKETS
  123. /* Supported Protocols */
  124. #define ProtoRasMol   0x01
  125.  
  126. typedef struct {
  127.         int protocol;
  128.         int socket;
  129.     } IPCConv;
  130.  
  131. #define MaxConvNum     8
  132. static IPCConv ConvData[MaxConvNum];
  133. static int ConvCount;
  134.  
  135. static int UseSockets;
  136. static int SocketNo;
  137. #endif  /* SOCKETS */
  138. #endif  /* TERMIOS */
  139.  
  140.  
  141. static char *FileNamePtr;
  142. static char *ScriptNamePtr;
  143. static int LabelOptFlag;
  144. static int FileFormat;
  145. static int ProfCount;
  146. static int LexState;
  147.  
  148. /* Function Prototype */
  149. #ifdef FUNCPROTO
  150. int HandleEvents( int );
  151. #else
  152. int HandleEvents();
  153. #endif
  154. int ProcessCommand();
  155. void RasMolExit();
  156.  
  157.  
  158. /* Either stdout or stderr */
  159. #define OutFp stdout
  160.  
  161. #ifdef APP
  162. void WriteChar( ch )
  163.     char ch;
  164. {   NXWriteChar( ch );
  165. }
  166.  
  167. void WriteString( ptr )
  168.     char *ptr;
  169. {   NXWriteString( ptr );
  170. }
  171. #else
  172. void WriteChar( ch )
  173.     char ch;
  174. {   putc(ch,OutFp);
  175. }
  176.  
  177. void WriteString( ptr )
  178.     char *ptr;
  179. {   fputs(ptr,OutFp);
  180. }
  181. #endif
  182.  
  183. static void ResetTerminal()
  184. {
  185. #ifdef SOCKETS
  186.     register int i;
  187. #endif
  188.  
  189. #ifdef TERMIOS
  190.     if( isatty(FileNo) )
  191.         ioctl(FileNo, TCSETAW, &OrigTerm);
  192. #endif
  193.  
  194. #ifdef SOCKETS
  195.     if( UseSockets )
  196.     {   close(SocketNo);
  197.  
  198.         for( i=0; i<MaxConvNum; i++ )
  199.             if( ConvData[i].protocol )
  200.                 close(ConvData[i].socket);
  201.     }
  202. #endif
  203.  
  204. #ifdef VMS
  205.     StdInFlag = False;
  206.     if( StdInStatus & 0x01 )
  207.         sys$cancel(StdInChan);
  208.  
  209.     sys$qiow( 0, StdInChan, IO$_SETMODE, 0, 0, 0,
  210.               StdInOrig, 12, 0, 0, 0, 0 );
  211. #endif
  212. }
  213.  
  214.  
  215.  
  216. void RasMolExit()
  217. {
  218.     WriteChar('\n');
  219.     if( CommandActive )
  220.         WriteChar('\n');
  221.  
  222.     if( Interactive )
  223.         CloseDisplay();
  224.     ResetTerminal();
  225.     exit(0);
  226. }
  227.  
  228.  
  229. void RasMolFatalExit( msg )
  230.     char *msg;
  231. {
  232.     WriteChar('\n');
  233.     WriteString(msg);
  234.     WriteChar('\n');
  235.     WriteChar(0x07);
  236.  
  237.     if( Interactive )
  238.         CloseDisplay();
  239.     ResetTerminal();
  240.     exit(1);
  241. }
  242.  
  243.  
  244. #ifdef VMS
  245. static int StdInASTEvent()
  246. {
  247.     register int ch;
  248.     register int i;
  249.  
  250.     if( !StdInFlag )
  251.         return( False );
  252.  
  253.     if( StdInBlck[0] & 0x01 )
  254.     {   if( StdInBlck[1] )
  255.         {   if( (StdInChar==0x03) || (StdInChar==0x1a) )
  256.                 RasMolFatalExit("*** Quit ***");
  257.  
  258.             if( LexState == 0 )
  259.             {   if( StdInChar == 0x1b )
  260.                 {   LexState = 1;  ch = 0;
  261.                 } else ch = StdInChar;
  262.  
  263.             } else if( LexState == 1 )
  264.             {   if( StdInChar=='[' )
  265.                 {   LexState = 2;  ch = 0;
  266.                 } else if( StdInChar=='O' )
  267.                 {   LexState = 3;  ch = 0;
  268.                 } else if( StdInChar != 0x1b )
  269.                 {   LexState = 0;  ch = StdInChar;
  270.                 } else ch = 0;
  271.  
  272.             } else /* LexState == 2 or 3 */
  273.             {   LexState = 0;
  274.                 switch( StdInChar )
  275.                 {   case('A'): ch = 0x10;  break;
  276.                     case('B'): ch = 0x0e;  break;
  277.                     case('C'): ch = 0x06;  break;
  278.                     case('D'): ch = 0x02;  break;
  279.                     default:   if( LexState==2 )
  280.                                {      ProcessCharacter('[');
  281.                                } else ProcessCharacter('O');
  282.  
  283.                                if( StdInChar == 0x1b )
  284.                                {   LexState = 1;  ch = 0;
  285.                                } else ch = StdInChar;
  286.                 }
  287.             }
  288.         } else ch = '\n';
  289.  
  290.         if( ch && ProcessCharacter(ch) )
  291.         {   if( ProcessCommand() )
  292.                 RasMolExit();
  293.  
  294.             if( !CommandActive )
  295.                 ResetCommandLine(0);
  296.         }
  297.     }
  298.  
  299.     /* Queue an Asynchronous I/O Request */
  300.     StdInStatus = sys$qio( 0, StdInChan, IO$_READVBLK|IO$M_NOECHO, 
  301.                            StdInBlck, StdInASTEvent, 0, &StdInChar, 
  302.                            1, 0, StdInMask, 0, 0);
  303.     return( True );
  304. }
  305. #endif  /* VMS */
  306.  
  307.  
  308. #ifdef SOCKETS
  309. static int OpenSocket()
  310. {
  311.     struct sockaddr_in addr;
  312.     register int i;
  313.  
  314.     UseSockets = False;
  315.     SocketNo = socket(AF_INET, SOCK_STREAM, 0);
  316.     if( SocketNo < 0 ) return( False );
  317.  
  318.     addr.sin_family = AF_INET;
  319.     addr.sin_addr.s_addr = INADDR_ANY;
  320.     addr.sin_port = htons(21069);
  321.  
  322.     if( bind(SocketNo, (struct sockaddr*)&addr, sizeof(addr)) )
  323.     {   close(SocketNo);
  324.         return( False );
  325.     }
  326.  
  327.     UseSockets = True;
  328.     for( i=0; i<MaxConvNum; i++ )
  329.         ConvData[i].protocol = 0;
  330.  
  331.     listen( SocketNo, 5 );
  332.     return( True );
  333. }
  334.  
  335.  
  336. static int OpenConnection( socket )
  337.     int socket;
  338. {
  339.     register int i;
  340.  
  341.     for( i=0; i<MaxConvNum; i++ )
  342.         if( !ConvData[i].protocol )
  343.         {   FD_SET(socket,&OrigWaitSet);
  344.             if( socket >= WaitWidth )
  345.                 WaitWidth = socket+1;
  346.  
  347.             ConvData[i].protocol = ProtoRasMol;
  348.             ConvData[i].socket = socket;
  349.             return( True );
  350.         }
  351.  
  352.     close( socket );
  353.     return( False );
  354. }
  355.  
  356. static void CloseConnection( conv )
  357.     int conv;
  358. {
  359.     FD_CLR(ConvData[conv].socket,&OrigWaitSet);
  360.     close( ConvData[conv].socket );
  361.     ConvData[conv].protocol = 0;
  362. }
  363.  
  364. static void HandleSocketData( conv )
  365.     int conv;
  366. {
  367.     register char *src,*dst;
  368.     register int result;
  369.     register int ch,len;
  370.     char buffer[4097];
  371.  
  372.     len = read( ConvData[conv].socket, buffer, 4096 );
  373.     if( len > 0 )
  374.     {   buffer[len] = '\0';
  375.         src = dst = buffer;
  376.         while( (ch = *src++) )
  377.             if( (ch>=' ') && (ch<='~') )
  378.                 *dst++ = ch;
  379.         *dst = '\0';
  380.         
  381.         result = ExecuteIPCCommand(buffer);
  382.         if( result == 2 )
  383.             RasMolExit();
  384.     } else CloseConnection( conv );
  385. }
  386. #endif /* SOCKETS */
  387.  
  388.  
  389.  
  390. static void InitTerminal(sockets)
  391.     int sockets;
  392. {
  393. #ifdef TERMIOS
  394.     register int i;
  395. #endif
  396.  
  397. #ifdef SIGTTIN
  398.     signal(SIGTTIN,SIG_IGN);
  399. #endif
  400. #ifdef SIGTTOU
  401.     signal(SIGTTOU,SIG_IGN);
  402. #endif
  403.  
  404. #ifdef TERMIOS
  405.     FileNo = fileno(stdin);
  406.     FD_ZERO(&OrigWaitSet);
  407.     FD_SET(FileNo,&OrigWaitSet);
  408.     WaitWidth = FileNo+1;
  409.  
  410. #ifdef SOCKETS
  411.     OpenSocket();
  412.     if( UseSockets )
  413.     {   FD_SET(SocketNo,&OrigWaitSet);
  414.         if( SocketNo >= WaitWidth )
  415.             WaitWidth = SocketNo+1;
  416.     }
  417. #endif
  418.  
  419.     for( i=0; i<32; i++ )
  420.         if( sockets & (1<<i) )
  421.         {   if( i >= WaitWidth )
  422.                 WaitWidth = i+1;
  423.             FD_SET(i,&OrigWaitSet);
  424.         }
  425.  
  426.  
  427.     if( isatty(FileNo) )
  428.     {   ioctl(FileNo, TCGETA, &OrigTerm);
  429.         IntrTerm = OrigTerm;
  430.  
  431.         IntrTerm.c_iflag |= IGNBRK|IGNPAR;
  432.         IntrTerm.c_iflag &= ~(BRKINT|PARMRK|INPCK|IXON|IXOFF);
  433.         IntrTerm.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH);
  434.         IntrTerm.c_lflag |= ISIG;
  435.  
  436.         IntrTerm.c_cc[VMIN] = 1;
  437.         IntrTerm.c_cc[VTIME] = 0;
  438.  
  439. #ifdef VSUSP /* Disable ^Z */
  440.         IntrTerm.c_cc[VSUSP] = 0;
  441. #endif
  442.  
  443.         ioctl(FileNo, TCSETAW, &IntrTerm);
  444.     }
  445. #endif /* TERMIOS */
  446.  
  447. #ifdef VMS
  448.     /* Associate "SYS$INPUT" with channel StdInChan! */
  449.     StdInStatus = sys$assign(&StdInDesc, &StdInChan, 0, 0, 0);
  450.     if( StdInStatus & 0x01 )
  451.     {   StdInFlag = True;
  452.  
  453.         /* Determine Original Terminal Mode */
  454.         sys$qiow( 0, StdInChan, IO$_SENSEMODE, 0, 0, 0,
  455.                   StdInOrig, 12, 0, 0, 0, 0 );
  456.  
  457.         StdInMode[0] = StdInOrig[0];
  458.         StdInMode[1] = StdInOrig[1];
  459.         StdInMode[2] = StdInOrig[2];
  460.  
  461.         /* Select "RAW" Terminal Mode */
  462.         StdInMode[2] |= TT2$M_PASTHRU;
  463.  
  464.         /* Set Current Terminal Mode */
  465.         sys$qiow( 0, StdInChan, IO$_SETMODE, 0, 0, 0,
  466.                   StdInMode, 12, 0, 0, 0, 0 );
  467.  
  468.         if( sockets )
  469.         {   /* Queue an Asynchronous I/O Request */
  470.             StdInStatus = sys$qio( 0, StdInChan, IO$_READVBLK|IO$M_NOECHO, 
  471.                                    StdInBlck, StdInASTEvent, 0, &StdInChar, 
  472.                                    1, 0, StdInMask, 0, 0);
  473.         } else StdInStatus = False;
  474.     } else StdInFlag = False;
  475.  
  476. #else /* !VMS */
  477.     setbuf(stdin,(char*)NULL);
  478. #endif
  479. }
  480.  
  481.  
  482. static int FetchCharacter()
  483. {
  484. #ifdef TERMIOS
  485.     register int status;
  486. #ifdef SOCKETS
  487.     register int i;
  488. #endif
  489.  
  490.     if( Interactive || UseSockets )
  491.         do {
  492.             if( !CommandActive )
  493.                 ResetCommandLine(0);
  494.  
  495.             if( Interactive )
  496.             {   HandleEvents(False);
  497.  
  498.                 /* avoid slow response time */
  499.                 if( !CommandActive )
  500.                     ResetCommandLine(0);
  501.             }
  502.  
  503.             TimeOut.tv_sec = 1;
  504.             TimeOut.tv_usec = 0;
  505.             WaitSet = OrigWaitSet;
  506. #ifdef __hpux
  507.             status = select( WaitWidth, (int*)&WaitSet, (int*)NULL, 
  508.                                         (int*)NULL, &TimeOut );
  509. #else
  510.             status = select( WaitWidth, &WaitSet, (struct fd_set*)NULL, 
  511.                                         (struct fd_set*)NULL, &TimeOut );
  512. #endif
  513.  
  514. #ifdef SOCKETS
  515.             if( UseSockets )
  516.             {   if( FD_ISSET(SocketNo,&WaitSet) )
  517.                 {   OpenConnection( accept(SocketNo,0,0) );
  518.                 } else for( i=0; i<MaxConvNum; i++ )
  519.                     if( ConvData[i].protocol )
  520.                         if( FD_ISSET(ConvData[i].socket,&WaitSet) )
  521.                             HandleSocketData( i );
  522.             }
  523. #endif
  524.         } while( (status<1) || !FD_ISSET(FileNo,&WaitSet) );
  525. #endif /* TERMIOS */
  526.  
  527.     if( !CommandActive )
  528.         ResetCommandLine(0);
  529.  
  530. #ifdef VMS
  531.     sys$qiow( 0, StdInChan, IO$_READVBLK|IO$M_NOECHO, StdInBlck,
  532.               0, 0, &StdInChar, 1, 0, StdInMask, 0, 0);
  533.     return( StdInChar );
  534. #else
  535.     return( getc(stdin) );
  536. #endif
  537. }
  538.  
  539. static int ReadCharacter()
  540. {
  541.     register int tmp;
  542.     register int ch;
  543.  
  544.     if( LexState )
  545.     {   ch = LexState;
  546.         LexState = 0;
  547.         return( ch );
  548.     }
  549.  
  550.     ch = FetchCharacter();
  551.     if( ch!=0x1b ) return( ch );
  552.  
  553.     ch = FetchCharacter();
  554.     if( (ch!='[') && (ch!='O') ) 
  555.         return( ch );
  556.  
  557.     switch( tmp=FetchCharacter() )
  558.     {   case('A'): return( 0x10 );
  559.         case('B'): return( 0x0e );
  560.         case('C'): return( 0x06 );
  561.         case('D'): return( 0x02 );
  562.     }
  563.     LexState = tmp;
  564.     return(ch);
  565. }
  566.  
  567.  
  568. void RasMolSignalExit( i )
  569.     int i;
  570. {
  571.     RasMolFatalExit("*** Quit ***");
  572. }
  573.  
  574.  
  575. static void LoadInitFile()
  576. {
  577.     register char *src,*dst;
  578.     register FILE *initrc;
  579.     register char *fname;
  580.     char fnamebuf[128];
  581.  
  582. #ifdef VMS
  583.     fname = "RASMOL.INI";
  584. #else
  585.     fname = ".rasmolrc";
  586. #endif
  587.  
  588.     initrc = fopen(fname,"r");
  589.     if( !initrc && (src=(char*)getenv("HOME")) )
  590.     {   dst = fnamebuf; 
  591.         while( *src )
  592.             *dst++ = *src++;
  593. #ifndef VMS
  594.         *dst++ = '/';
  595. #endif
  596.  
  597.         src = fname; fname = fnamebuf;
  598.         while( (*dst++ = *src++) );
  599.         initrc = fopen(fname,"r");
  600.     }
  601.  
  602.     if( !initrc && (src=(char*)getenv("RASMOLPATH")) )
  603.     {   dst = fnamebuf; 
  604.         while( *src )
  605.             *dst++ = *src++;
  606. #ifndef VMS
  607.         *dst++ = '/';
  608. #endif
  609.  
  610.         src = "rasmolrc"; fname = fnamebuf;
  611.         while( (*dst++ = *src++) );
  612.         initrc = fopen(fname,"r");
  613.     }
  614.  
  615.     if( initrc )
  616.         LoadScriptFile(initrc,fname);
  617. }
  618.  
  619.  
  620. static void HandleMenu( hand )
  621.      int hand;
  622. {
  623.     register int menu;
  624.     register int item;
  625.     register int mask;
  626.  
  627.     menu = hand>>8;
  628.     item = hand&0xff;
  629.     switch( menu )
  630.     {   case(0):  /* File Menu */
  631.                   switch( item )
  632.                   {   case(1):  /* Open */
  633.                                 if( !Database )
  634.                                     ResetCommandLine(2);
  635.                                 break;
  636.  
  637.                       case(2):  /* Save As */
  638.                                 if( Database )
  639.                                     ResetCommandLine(4);
  640.                                 break;
  641.  
  642.                       case(3):  /* Close */
  643.                                 ZapDatabase();
  644.                                 break;
  645.  
  646.                       case(5):  /* Exit */
  647.                                 RasMolExit();
  648.                                 break;
  649.                   } 
  650.                   break;
  651.  
  652.         case(1):  /* Display Menu */
  653.                   switch( item )
  654.                   {   case(1):  /* Wireframe */
  655.                                 DisableSpacefill();
  656.                                 EnableWireframe(WireFlag,0);
  657.                                 SetRibbonStatus(False,0,0);
  658.                                 DisableBackbone();
  659.                                 ReDrawFlag |= RFRefresh;
  660.                                 break;
  661.  
  662.                       case(2):  /* Backbone */
  663.                                 DisableSpacefill();
  664.                                 DisableWireframe();
  665.                                 SetRibbonStatus(False,0,0);
  666.                                 EnableBackbone(CylinderFlag,80);
  667.                                 ReDrawFlag |= RFRefresh;
  668.                                 break;
  669.  
  670.                       case(3):  /* Sticks */
  671.                                 DisableSpacefill();
  672.                                 if( MainAtomCount<256 )
  673.                                 {   EnableWireframe(CylinderFlag,40);
  674.                                 } else EnableWireframe(CylinderFlag,80);
  675.                                 SetRibbonStatus(False,0,0);
  676.                                 ReDrawFlag |= RFRefresh;
  677.                                 DisableBackbone();
  678.                                 break;
  679.  
  680.                       case(4):  /* Spheres */
  681.                                 SetVanWaalRadius();
  682.                                 DisableWireframe();
  683.                                 SetRibbonStatus(False,0,0);
  684.                                 DisableBackbone();
  685.                                 ReDrawFlag |= RFRefresh;
  686.                                 break;
  687.  
  688.                       case(5):  /* Ball & Stick */
  689.                                 SetRadiusValue(120);
  690.                                 EnableWireframe(CylinderFlag,40);
  691.                                 SetRibbonStatus(False,0,0);
  692.                                 DisableBackbone();
  693.                                 ReDrawFlag |= RFRefresh;
  694.                                 break;
  695.  
  696.                       case(6):  /* Ribbons */
  697.                                 DisableSpacefill();
  698.                                 DisableWireframe();
  699.                                 SetRibbonStatus(True,RibbonFlag,0);
  700.                                 DisableBackbone();
  701.                                 ReDrawFlag |= RFRefresh;
  702.                                 break;
  703.  
  704.                       case(7):  /* Strands */
  705.                                 DisableSpacefill();
  706.                                 DisableWireframe();
  707.                                 SetRibbonStatus(True,StrandFlag,0);
  708.                                 DisableBackbone();
  709.                                 ReDrawFlag |= RFRefresh;
  710.                                 break;
  711.  
  712.                       case(8):  /* Cartoons */
  713.                                 DisableSpacefill();
  714.                                 DisableWireframe();
  715.                                 SetRibbonCartoons();
  716.                                 DisableBackbone();
  717.                                 ReDrawFlag |= RFRefresh;
  718.                   }
  719.                   break;
  720.  
  721.         case(2):  /* Colours Menu */
  722.                   switch( item )
  723.                   {   case(1):  /* Monochrome */
  724.                                 MonoColourAttrib(255,255,255);
  725.                                 ReDrawFlag |= RFColour;  break;
  726.                       case(2):  /* CPK */
  727.                                 CPKColourAttrib();
  728.                                 ReDrawFlag |= RFColour;  break;
  729.                       case(3):  /* Shapely */
  730.                                 ShapelyColourAttrib();
  731.                                 ReDrawFlag |= RFColour;  break;
  732.                       case(4):  /* Group */
  733.                                 ScaleColourAttrib( GroupAttr );
  734.                                 ReDrawFlag |= RFColour;  break;
  735.                       case(5):  /* Chain */
  736.                                 ScaleColourAttrib( ChainAttr );
  737.                                 ReDrawFlag |= RFColour;  break;
  738.                       case(6):  /* Temperature */
  739.                                 ScaleColourAttrib( TempAttr );
  740.                                 ReDrawFlag |= RFColour;  break;
  741.                       case(7):  /* Structure */
  742.                                 StructColourAttrib();
  743.                                 ReDrawFlag |= RFColour;  break;
  744.                       case(8):  /* User */
  745.                                 UserMaskAttrib(MaskColourFlag);
  746.                                 ReDrawFlag |= RFColour;  break;
  747.                   }
  748.                   break;
  749.  
  750.         case(3):  /* Option Menu */
  751.                   switch( item )
  752.                   {   case(1):  /* Slabbing */
  753.                                 ReDrawFlag |= RFRefresh;
  754.                                 UseSlabPlane = !UseSlabPlane;
  755.                                 if( UseSlabPlane )
  756.                                     UseShadow = False;
  757.                                 break;
  758.  
  759.                       case(2):  /* Hydrogens */
  760.                                 mask = NormAtomFlag;
  761.                                 if( HetaGroups )
  762.                                     mask |= HeteroFlag;
  763.                                 Hydrogens = !Hydrogens;
  764.                                 ReDrawFlag |= RFRefresh;
  765.                                       
  766.                                 if( Hydrogens )
  767.                                 {   SelectZone(mask|HydrogenFlag);
  768.                                 } else RestrictZone(mask);
  769.                                 break;
  770.  
  771.                       case(3):  /* Hetero Atoms */
  772.                                 mask = NormAtomFlag;
  773.                                 if( Hydrogens )
  774.                                     mask |= HydrogenFlag;
  775.                                 HetaGroups = !HetaGroups;
  776.                                 ReDrawFlag |= RFRefresh;
  777.                                 
  778.                                 if( HetaGroups )
  779.                                 {   SelectZone(mask|HeteroFlag);
  780.                                 } else RestrictZone(mask);
  781.                                 break;
  782.  
  783.                       case(4):  /* Specular */
  784.                                 FakeSpecular = !FakeSpecular;
  785.                                 ReDrawFlag |= RFColour;
  786.                                 break;
  787.  
  788.                       case(5):  /* Shadows */
  789.                                 ReDrawFlag |= RFRefresh;
  790.                                 UseShadow = !UseShadow;
  791.                                 if( UseShadow )
  792.                                 {   ReviseInvMatrix();
  793.                                     VoxelsClean = False;
  794.                                     UseSlabPlane = False;
  795.                                     ReAllocBuffers();
  796.                                 }
  797.                                 break;
  798.  
  799.                       case(6):  /* Stereo */
  800.                                 if( UseStereo )
  801.                                 {   SetStereoMode(False);
  802.                                 } else SetStereoMode(True);
  803.                                 ReDrawFlag |= RFRefresh;
  804.                                 break;
  805.  
  806.                       case(7):  /* Labels */
  807.                                 LabelOptFlag = !LabelOptFlag;
  808.                                 DefaultLabels(LabelOptFlag);
  809.                                 ReDrawFlag |= RFRefresh;
  810.                                 break;
  811.                   }
  812.                   break;
  813.  
  814.         case(4):  /* Export Menu */
  815.                   ResetCommandLine(3);
  816.                   StateOption = item;
  817.                   break;
  818.  
  819.         case(5):  /* Help Menu */
  820.                   break;
  821.     }
  822. }
  823.  
  824.  
  825. void RefreshScreen()
  826. {
  827.     if( !UseSlabPlane )
  828.     {   ReDrawFlag &= ~(RFTransZ|RFSlab|RFPoint);
  829.     } else ReDrawFlag &= ~(RFTransZ|RFPoint);
  830.  
  831.     if( ReDrawFlag )
  832.     {   if( ReDrawFlag & RFReSize )
  833.             ReSizeScreen();
  834.  
  835.         if( ReDrawFlag & RFColour )
  836.         {   if( Interactive ) 
  837.                 ClearImage();
  838.             DefineColourMap();
  839.         }
  840.  
  841.         if( Database )
  842.         {   if( Interactive )
  843.                 BeginWait();
  844.             if( ReDrawFlag & RFApply ) 
  845.                 ApplyTransform();
  846.             DrawFrame();
  847.             if( Interactive )
  848.             {   TransferImage();
  849.                 EndWait();
  850.             }
  851.         } else if( Interactive )
  852.         {   ClearBuffers();
  853.             TransferImage();
  854.         }
  855.         ReDrawFlag = 0;
  856.     }
  857. }
  858.  
  859.  
  860. void AdviseUpdate( item )
  861.     int item;
  862. {
  863. }
  864.  
  865.  
  866. int ProcessCommand()
  867. {
  868.     switch(CurState)
  869.     {   case(1):  /* RasMol Prompt */
  870.                   return( ExecuteCommand() );
  871.  
  872.         case(2):  /* PDB Filename */
  873.                   if( *CurLine && FetchFile(FormatPDB,False,CurLine) )
  874.                   {   ReDrawFlag |= RFRefresh | RFColour;
  875.                       if( InfoBondCount < 1 )
  876.                       {   EnableBackbone(CylinderFlag,80);
  877.                       } else EnableWireframe(WireFlag,0);
  878.                       CPKColourAttrib();
  879.                   }
  880.                   ResetCommandLine(1);
  881.                   break;
  882.  
  883.         case(3):  /* Export Image Filename */
  884.                   if( *CurLine ) switch( StateOption )
  885.                   {   case(1):   WriteGIFFile(CurLine);            break;
  886.                       case(2):   WriteEPSFFile(CurLine,True,True); break;
  887.                       case(3):   WritePPMFile(CurLine,True);       break;
  888.                       case(4):   WriteIRISFile(CurLine);           break;
  889.                       case(5):   WriteRastFile(CurLine,True);      break;
  890.                       case(6):   WriteBMPFile(CurLine);            break;
  891.                       case(7):   WritePICTFile(CurLine);           break;
  892.                   }
  893.                   ResetCommandLine(1);
  894.                   break;
  895.  
  896.         case(4):  /* Save Molecule Filename */
  897.                   if( *CurLine )
  898.                       SavePDBMolecule(CurLine);
  899.                   ResetCommandLine(1);
  900.                   break;
  901.     }
  902.     return( False );
  903. }
  904.  
  905.  
  906. int HandleEvents( wait )
  907.     int wait;
  908. {
  909.     register int result;
  910.  
  911.     result = FetchEvent( wait );
  912.     while( ReDrawFlag || result )
  913.     {   if( !result )
  914.         {   if( ReDrawFlag&RFPoint )
  915.             {   if( Database )
  916.                 {   if( ReDrawFlag & RFPoint1 )
  917.                     {      PickAtom(True,PointX,PointY);
  918.                     } else PickAtom(False,PointX,PointY);
  919.                 }
  920.                 ReDrawFlag &= ~RFPoint;
  921.             }
  922.  
  923.             if( ReDrawFlag )
  924.                 RefreshScreen();
  925.         } else if( !IsPaused )
  926.             HandleMenu( result );
  927.         result = FetchEvent( False );
  928.     }
  929.     return( True );
  930. }
  931.  
  932.  
  933. static void ProfileExecution()
  934. {
  935.     register long start,stop;
  936.     register Real delta;
  937.     register int i;
  938.  
  939.     delta = TwoPi/ProfCount;
  940.  
  941.     printf("Profiling Execution!\n");
  942.  
  943.     start = time((time_t *)NULL);
  944.     for( i=0; i<ProfCount; i++ )
  945.     {   DrawFrame();
  946.         if( Interactive )
  947.             TransferImage();
  948.         ReDrawFlag |= RFRotateY;
  949.         DialValue[1] += delta;
  950.         /* UpdateScrollBars(); */
  951.         ApplyTransform();
  952.     }
  953.  
  954.     stop = time((time_t *)NULL);
  955.     fprintf(OutFp,"Execution of %d frames\n",ProfCount);
  956.     fprintf(OutFp,"Duration = %ld seconds\n",stop-start);
  957.     RasMolExit();
  958. }
  959.  
  960.  
  961. static void DisplayUsage()
  962. {
  963.     fputs("usage: rasmol [-nodisplay] [-script scriptfile] ",OutFp);
  964.     fputs("[[-format] file]\n    formats: -pdb -nmrpdb ",OutFp);
  965.     fputs("-mopac -mdl -mol2 -xyz -alchemy -charmm\n\n",OutFp);
  966.     exit(1);
  967. }
  968.  
  969.  
  970. #define FORMATOPTMAX   15
  971. static struct {
  972.         char *ident;
  973.         int format;
  974.     } FormatOpt[FORMATOPTMAX] = { 
  975.             { "alchemy",    FormatAlchemy  },
  976.             { "biosym",     FormatBiosym   },
  977.             { "cif",        FormatCIF      },
  978.             { "charmm",     FormatCharmm   },
  979.             { "fdat",       FormatFDAT     },
  980.             { "gaussian",   FormatGaussian },
  981.             { "macromodel", FormatMacroMod },
  982.             { "mdl",        FormatMDL      },
  983.             { "mmdb",       FormatMMDB     },
  984.             { "mol2",       FormatMol2     },
  985.             { "mopac",      FormatMOPAC    },
  986.             { "nmrpdb",     FormatNMRPDB   },
  987.             { "pdb",        FormatPDB      },
  988.             { "shelx",      FormatSHELX    },
  989.             { "xyz",        FormatXYZ      }
  990.                                 };
  991.     
  992. static void ProcessOptions(argc,argv)
  993.     int argc;  char *argv[];
  994. {
  995.     register char *ptr;
  996.     register int i,j;
  997.  
  998.     for( i=1; i<argc; i++ )
  999.     {   ptr = argv[i];
  1000. #ifdef VMS
  1001.         if( (*ptr=='/') || (*ptr=='-') )
  1002. #else
  1003.         if( *ptr == '-' )
  1004. #endif
  1005.         {   ptr++;
  1006.  
  1007.             if( !strcmp(ptr,"nodisplay") )
  1008.             {   Interactive = False;
  1009.             } else if( !strcmp(ptr,"prof") ||
  1010.                        !strcmp(ptr,"profile") )
  1011.             {   ProfCount = 200;
  1012.             } else if( !strcmp(ptr,"script") )
  1013.             {   if( i != argc-1 )
  1014.                 {   ScriptNamePtr = argv[++i];
  1015.                 } else DisplayUsage();
  1016.  
  1017.             } else if( !strcmp(ptr,"sybyl") )
  1018.             {   FileFormat = FormatMol2;
  1019.             } else if( !strcmp(ptr,"pdbnmr") )
  1020.             {   FileFormat = FormatNMRPDB;
  1021. #ifdef CEXIOLIB
  1022.             } else if( !strcmp(ptr,"cex") )
  1023.             {   FileFormat = FormatCEX;
  1024. #endif
  1025.  
  1026.             } else  /* File Formats! */
  1027.             {   for( j=0; j<FORMATOPTMAX; j++ )
  1028.                     if( !strcmp(ptr,FormatOpt[j].ident) )
  1029.                     {   FileFormat = FormatOpt[j].format;
  1030.                         break;
  1031.                     }
  1032.  
  1033.                 if( j==FORMATOPTMAX )
  1034.                     DisplayUsage();
  1035.             }
  1036.         } else
  1037.             if( !FileNamePtr )
  1038.             {   FileNamePtr = ptr;
  1039.             } else DisplayUsage();
  1040.     }
  1041. }
  1042.  
  1043. #ifdef APP
  1044. void ras_init(void)
  1045. {
  1046.     int argc=1;
  1047.     char *argv[] = {{"rasmol"},NULL};
  1048. #else
  1049. int main(argc,argv)
  1050. int argc; char *argv[];
  1051. {
  1052. #endif
  1053.     register FILE *fp;
  1054.     register int temp;
  1055.     register char ch;
  1056.  
  1057.     FileNamePtr = NULL;
  1058.     ScriptNamePtr = NULL;
  1059.     FileFormat = FormatPDB;
  1060.     LabelOptFlag = False;
  1061.     Interactive = True;
  1062.     ProfCount = 0;
  1063.  
  1064.     ProcessOptions(argc,argv);
  1065.     ReDrawFlag = 0;
  1066.     
  1067.     temp = Interactive;
  1068.     setbuf(OutFp,(char *)NULL);
  1069.     Interactive = OpenDisplay(XRange, YRange);
  1070.     InitTerminal(Interactive);
  1071.     signal(SIGINT,RasMolSignalExit);
  1072.  
  1073.     WriteString("RasMol Molecular Renderer\n");
  1074.     WriteString("Roger Sayle, August 1995\n");
  1075.     WriteString("Version 2.6\n");
  1076.  
  1077. #ifdef EIGHTBIT
  1078.     WriteString("[8bit version]\n\n");
  1079. #else
  1080. #ifdef SIXTEENBIT
  1081.     WriteString("[16bit version]\n\n");
  1082. #else
  1083.     WriteString("[24bit version]\n\n");
  1084. #endif
  1085. #endif
  1086.  
  1087.     if( !Interactive )
  1088.     {   if( temp )
  1089.         {   WriteString("No suitable display detected!\n");
  1090.         } else WriteString("Display window disabled!\n");
  1091.     }
  1092.  
  1093.     InitialiseCommand();
  1094.     InitialiseTransform();
  1095.     InitialiseDatabase();
  1096.     InitialiseRenderer();
  1097.     InitialisePixUtils();
  1098.     InitialiseAbstree();
  1099.     InitialiseOutFile();
  1100.     InitialiseRepres();
  1101.  
  1102.     if( ProfCount )
  1103.     {   if( !FileNamePtr || !FetchFile(FileFormat,True,FileNamePtr) )
  1104.             RasMolFatalExit("Profile Error: Invalid PDB file name!");
  1105.         ReDrawFlag |= RFRefresh | RFColour;
  1106.  
  1107.         /* SetVanWaalRadius(); */
  1108.         /* CPKColourAttrib();  */
  1109.  
  1110.         FakeSpecular = True;
  1111.         ScaleColourAttrib(GroupAttr);
  1112.         SetRibbonStatus(True,RibbonFlag,0);
  1113.         EnableWireframe(WireFlag,0);
  1114.         RefreshScreen();
  1115.  
  1116.         /* Avoid Pending Events */
  1117.         if( Interactive ) 
  1118.         {   FetchEvent(False);
  1119.             if( ReDrawFlag )
  1120.                 RefreshScreen();
  1121.         }
  1122.         ProfileExecution();
  1123.     }
  1124.  
  1125.     if( FileNamePtr && FetchFile(FileFormat,True,FileNamePtr) )
  1126.     {   ReDrawFlag |= RFRefresh | RFColour;
  1127.         if( InfoBondCount < 1 )
  1128.         {   EnableBackbone(CylinderFlag,80);
  1129.         } else EnableWireframe(WireFlag,0);
  1130.         CPKColourAttrib();
  1131.         RefreshScreen();
  1132.     }
  1133.  
  1134.     LexState = 0;
  1135.     WriteString("Type \"help\" for help!\n");
  1136.     ResetCommandLine(1);
  1137.  
  1138.     LoadInitFile();
  1139.     if( ScriptNamePtr )
  1140.     {   if( (fp=fopen(ScriptNamePtr,"r")) )
  1141.         {   LoadScriptFile(fp,ScriptNamePtr);
  1142.             fclose(fp);
  1143.         } else fprintf(OutFp,"Error: File '%s' not found!\n",ScriptNamePtr);
  1144.     }
  1145.  
  1146. #ifndef APP
  1147. #ifndef TERMIOS
  1148.     if( Interactive )
  1149.     {   while( HandleEvents(True) )
  1150.             if( !CommandActive )
  1151.                 ResetCommandLine(0);
  1152.     } else
  1153. #endif
  1154.     while( True )
  1155.     {   ch = ReadCharacter();
  1156.         if( ProcessCharacter(ch) )
  1157.             if( ProcessCommand() )
  1158.                 break;
  1159.         RefreshScreen();
  1160.     }
  1161.     RasMolExit();
  1162.     return( 0 );
  1163. #endif
  1164. }
  1165.  
  1166.