/* rasmol.c * RasMol2 Molecular Graphics * Roger Sayle, August 1995 * Version 2.6 */ #ifndef sun386 #include #endif #include #include #include #define RASMOL #include "rasmol.h" #include "graphics.h" #include "molecule.h" #include "infile.h" #include "abstree.h" #include "transfor.h" #include "command.h" #include "render.h" #include "repres.h" #include "pixutils.h" #include "outfile.h" #ifdef TERMIOS #include #include #ifdef esv #include #else #ifdef __FreeBSD__ #include #include #define TCSETAW TIOCSETAW #define TCGETA TIOCGETA #else #ifdef _CONVEX_SOURCE #include #include "/usr/sys/base/h/ioctl.h" #define TCSETAW TIOCSETAW #define TCGETA TIOCGETA #else #include #endif /* _CONVEX_SOURCE */ #endif /* __FreeBSD__ */ #endif /* esv */ #ifdef esv #include #else #include #endif #if defined(_SEQUENT_) || defined(_AIX) #include #endif #ifdef __sgi /* Avoid 'bzero' Compiler Warnings! */ #include #endif #endif /* TERMIOS */ #ifdef VMS #include #include #include #include #include #endif #ifdef SOCKETS #include #include #include #endif #define TwoPi 6.2832 #ifdef VMS static struct { unsigned short size; unsigned short type; char *string; } StdInDesc = { 10, 0, "SYS$INPUT:" }; /* Character Terminator Mask! */ static int StdInMask[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static short StdInBlck[4]; static int StdInMode[3]; static int StdInOrig[3]; static short StdInChan; static int StdInStatus; static char StdInChar; static int StdInFlag; #endif #ifdef TERMIOS #ifdef __FreeBSD__ static struct termios OrigTerm; static struct termios IntrTerm; #else static struct termio OrigTerm; static struct termio IntrTerm; #endif static struct fd_set OrigWaitSet; static struct fd_set WaitSet; static struct timeval TimeOut; static int WaitWidth; static int FileNo; #ifdef SOCKETS /* Supported Protocols */ #define ProtoRasMol 0x01 typedef struct { int protocol; int socket; } IPCConv; #define MaxConvNum 8 static IPCConv ConvData[MaxConvNum]; static int ConvCount; static int UseSockets; static int SocketNo; #endif /* SOCKETS */ #endif /* TERMIOS */ static char *FileNamePtr; static char *ScriptNamePtr; static int LabelOptFlag; static int FileFormat; static int ProfCount; static int LexState; /* Function Prototype */ #ifdef FUNCPROTO int HandleEvents( int ); #else int HandleEvents(); #endif int ProcessCommand(); void RasMolExit(); /* Either stdout or stderr */ #define OutFp stdout void WriteChar( ch ) char ch; { putc(ch,OutFp); } void WriteString( ptr ) char *ptr; { fputs(ptr,OutFp); } static void ResetTerminal() { #ifdef SOCKETS register int i; #endif #ifdef TERMIOS if( isatty(FileNo) ) ioctl(FileNo, TCSETAW, &OrigTerm); #endif #ifdef SOCKETS if( UseSockets ) { close(SocketNo); for( i=0; i= WaitWidth ) WaitWidth = socket+1; ConvData[i].protocol = ProtoRasMol; ConvData[i].socket = socket; return( True ); } close( socket ); return( False ); } static void CloseConnection( conv ) int conv; { FD_CLR(ConvData[conv].socket,&OrigWaitSet); close( ConvData[conv].socket ); ConvData[conv].protocol = 0; } static void HandleSocketData( conv ) int conv; { register char *src,*dst; register int result; register int ch,len; char buffer[4097]; len = read( ConvData[conv].socket, buffer, 4096 ); if( len > 0 ) { buffer[len] = '\0'; src = dst = buffer; while( (ch = *src++) ) if( (ch>=' ') && (ch<='~') ) *dst++ = ch; *dst = '\0'; result = ExecuteIPCCommand(buffer); if( result == IPC_Exit ) { CloseConnection( conv ); } else if( result == IPC_Quit ) RasMolExit(); } else CloseConnection( conv ); } #endif /* SOCKETS */ static void InitTerminal(sockets) int sockets; { #ifdef TERMIOS register int i; #endif #ifdef SIGTTIN signal(SIGTTIN,SIG_IGN); #endif #ifdef SIGTTOU signal(SIGTTOU,SIG_IGN); #endif #ifdef TERMIOS FileNo = fileno(stdin); FD_ZERO(&OrigWaitSet); FD_SET(FileNo,&OrigWaitSet); WaitWidth = FileNo+1; #ifdef SOCKETS OpenSocket(); if( UseSockets ) { FD_SET(SocketNo,&OrigWaitSet); if( SocketNo >= WaitWidth ) WaitWidth = SocketNo+1; } #endif for( i=0; i<32; i++ ) if( sockets & (1<= WaitWidth ) WaitWidth = i+1; FD_SET(i,&OrigWaitSet); } if( isatty(FileNo) ) { ioctl(FileNo, TCGETA, &OrigTerm); IntrTerm = OrigTerm; IntrTerm.c_iflag |= IGNBRK|IGNPAR; IntrTerm.c_iflag &= ~(BRKINT|PARMRK|INPCK|IXON|IXOFF); IntrTerm.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH); IntrTerm.c_lflag |= ISIG; IntrTerm.c_cc[VMIN] = 1; IntrTerm.c_cc[VTIME] = 0; #ifdef VSUSP /* Disable ^Z */ IntrTerm.c_cc[VSUSP] = 0; #endif ioctl(FileNo, TCSETAW, &IntrTerm); } #endif /* TERMIOS */ #ifdef VMS /* Associate "SYS$INPUT" with channel StdInChan! */ StdInStatus = sys$assign(&StdInDesc, &StdInChan, 0, 0, 0); if( StdInStatus & 0x01 ) { StdInFlag = True; /* Determine Original Terminal Mode */ sys$qiow( 0, StdInChan, IO$_SENSEMODE, 0, 0, 0, StdInOrig, 12, 0, 0, 0, 0 ); StdInMode[0] = StdInOrig[0]; StdInMode[1] = StdInOrig[1]; StdInMode[2] = StdInOrig[2]; /* Select "RAW" Terminal Mode */ StdInMode[2] |= TT2$M_PASTHRU; /* Set Current Terminal Mode */ sys$qiow( 0, StdInChan, IO$_SETMODE, 0, 0, 0, StdInMode, 12, 0, 0, 0, 0 ); if( sockets ) { /* Queue an Asynchronous I/O Request */ StdInStatus = sys$qio( 0, StdInChan, IO$_READVBLK|IO$M_NOECHO, StdInBlck, StdInASTEvent, 0, &StdInChar, 1, 0, StdInMask, 0, 0); } else StdInStatus = False; } else StdInFlag = False; #else /* !VMS */ setbuf(stdin,(char*)NULL); #endif } static int FetchCharacter() { #ifdef TERMIOS register int status; #ifdef SOCKETS register int i; #endif #ifdef SOCKETS if( Interactive || UseSockets ) #else if( Interactive ) #endif do { if( !CommandActive ) ResetCommandLine(0); if( Interactive ) { HandleEvents(False); /* avoid slow response time */ if( !CommandActive ) ResetCommandLine(0); } TimeOut.tv_sec = 1; TimeOut.tv_usec = 0; WaitSet = OrigWaitSet; #ifdef __hpux status = select( WaitWidth, (int*)&WaitSet, (int*)NULL, (int*)NULL, &TimeOut ); #else status = select( WaitWidth, &WaitSet, (struct fd_set*)NULL, (struct fd_set*)NULL, &TimeOut ); #endif #ifdef SOCKETS if( UseSockets ) { if( FD_ISSET(SocketNo,&WaitSet) ) { OpenConnection( accept(SocketNo,0,0) ); } else for( i=0; i>8; item = hand&0xff; switch( menu ) { case(0): /* File Menu */ switch( item ) { case(1): /* Open */ if( !Database ) ResetCommandLine(2); break; case(2): /* Save As */ if( Database ) ResetCommandLine(4); break; case(3): /* Close */ ZapDatabase(); break; case(5): /* Exit */ RasMolExit(); break; } break; case(1): /* Display Menu */ switch( item ) { case(1): /* Wireframe */ DisableSpacefill(); EnableWireframe(WireFlag,0); SetRibbonStatus(False,0,0); DisableBackbone(); ReDrawFlag |= RFRefresh; break; case(2): /* Backbone */ DisableSpacefill(); DisableWireframe(); SetRibbonStatus(False,0,0); EnableBackbone(CylinderFlag,80); ReDrawFlag |= RFRefresh; break; case(3): /* Sticks */ DisableSpacefill(); if( MainAtomCount<256 ) { EnableWireframe(CylinderFlag,40); } else EnableWireframe(CylinderFlag,80); SetRibbonStatus(False,0,0); ReDrawFlag |= RFRefresh; DisableBackbone(); break; case(4): /* Spheres */ SetVanWaalRadius(); DisableWireframe(); SetRibbonStatus(False,0,0); DisableBackbone(); ReDrawFlag |= RFRefresh; break; case(5): /* Ball & Stick */ SetRadiusValue(120); EnableWireframe(CylinderFlag,40); SetRibbonStatus(False,0,0); DisableBackbone(); ReDrawFlag |= RFRefresh; break; case(6): /* Ribbons */ DisableSpacefill(); DisableWireframe(); SetRibbonStatus(True,RibbonFlag,0); DisableBackbone(); ReDrawFlag |= RFRefresh; break; case(7): /* Strands */ DisableSpacefill(); DisableWireframe(); SetRibbonStatus(True,StrandFlag,0); DisableBackbone(); ReDrawFlag |= RFRefresh; break; case(8): /* Cartoons */ DisableSpacefill(); DisableWireframe(); SetRibbonCartoons(); DisableBackbone(); ReDrawFlag |= RFRefresh; } break; case(2): /* Colours Menu */ switch( item ) { case(1): /* Monochrome */ MonoColourAttrib(255,255,255); ReDrawFlag |= RFColour; break; case(2): /* CPK */ CPKColourAttrib(); ReDrawFlag |= RFColour; break; case(3): /* Shapely */ ShapelyColourAttrib(); ReDrawFlag |= RFColour; break; case(4): /* Group */ ScaleColourAttrib( GroupAttr ); ReDrawFlag |= RFColour; break; case(5): /* Chain */ ScaleColourAttrib( ChainAttr ); ReDrawFlag |= RFColour; break; case(6): /* Temperature */ ScaleColourAttrib( TempAttr ); ReDrawFlag |= RFColour; break; case(7): /* Structure */ StructColourAttrib(); ReDrawFlag |= RFColour; break; case(8): /* User */ UserMaskAttrib(MaskColourFlag); ReDrawFlag |= RFColour; break; } break; case(3): /* Option Menu */ switch( item ) { case(1): /* Slabbing */ ReDrawFlag |= RFRefresh; UseSlabPlane = !UseSlabPlane; if( UseSlabPlane ) UseShadow = False; break; case(2): /* Hydrogens */ mask = NormAtomFlag; if( HetaGroups ) mask |= HeteroFlag; Hydrogens = !Hydrogens; ReDrawFlag |= RFRefresh; if( Hydrogens ) { SelectZone(mask|HydrogenFlag); } else RestrictZone(mask); break; case(3): /* Hetero Atoms */ mask = NormAtomFlag; if( Hydrogens ) mask |= HydrogenFlag; HetaGroups = !HetaGroups; ReDrawFlag |= RFRefresh; if( HetaGroups ) { SelectZone(mask|HeteroFlag); } else RestrictZone(mask); break; case(4): /* Specular */ FakeSpecular = !FakeSpecular; ReDrawFlag |= RFColour; break; case(5): /* Shadows */ ReDrawFlag |= RFRefresh; UseShadow = !UseShadow; if( UseShadow ) { ReviseInvMatrix(); VoxelsClean = False; UseSlabPlane = False; ReAllocBuffers(); } break; case(6): /* Stereo */ if( UseStereo ) { SetStereoMode(False); } else SetStereoMode(True); ReDrawFlag |= RFRefresh; break; case(7): /* Labels */ LabelOptFlag = !LabelOptFlag; DefaultLabels(LabelOptFlag); ReDrawFlag |= RFRefresh; break; } break; case(4): /* Export Menu */ ResetCommandLine(3); StateOption = item; break; case(5): /* Help Menu */ break; } } void RefreshScreen() { if( !UseSlabPlane ) { ReDrawFlag &= ~(RFTransZ|RFSlab|RFPoint); } else ReDrawFlag &= ~(RFTransZ|RFPoint); if( ReDrawFlag ) { if( ReDrawFlag & RFReSize ) ReSizeScreen(); if( ReDrawFlag & RFColour ) { if( Interactive ) ClearImage(); DefineColourMap(); } if( Database ) { if( Interactive ) BeginWait(); if( ReDrawFlag & RFApply ) ApplyTransform(); DrawFrame(); if( Interactive ) { TransferImage(); EndWait(); } } else if( Interactive ) { ClearBuffers(); TransferImage(); } ReDrawFlag = 0; } } void AdviseUpdate( item ) int item; { } int ProcessCommand() { switch(CurState) { case(1): /* RasMol Prompt */ return( ExecuteCommand() ); case(2): /* PDB Filename */ if( *CurLine && FetchFile(FormatPDB,False,CurLine) ) { ReDrawFlag |= RFRefresh | RFColour; if( InfoBondCount < 1 ) { EnableBackbone(CylinderFlag,80); } else EnableWireframe(WireFlag,0); CPKColourAttrib(); } ResetCommandLine(1); break; case(3): /* Export Image Filename */ if( *CurLine ) switch( StateOption ) { case(1): WriteGIFFile(CurLine); break; case(2): WriteEPSFFile(CurLine,True,True); break; case(3): WritePPMFile(CurLine,True); break; case(4): WriteIRISFile(CurLine); break; case(5): WriteRastFile(CurLine,True); break; case(6): WriteBMPFile(CurLine); break; case(7): WritePICTFile(CurLine); break; } ResetCommandLine(1); break; case(4): /* Save Molecule Filename */ if( *CurLine ) SavePDBMolecule(CurLine); ResetCommandLine(1); break; } return( False ); } int HandleEvents( wait ) int wait; { register int result; result = FetchEvent( wait ); while( ReDrawFlag || result ) { if( !result ) { if( ReDrawFlag&RFPoint ) { if( Database ) { if( ReDrawFlag & RFPoint1 ) { PickAtom(True,PointX,PointY); } else PickAtom(False,PointX,PointY); } ReDrawFlag &= ~RFPoint; } if( ReDrawFlag ) RefreshScreen(); } else if( !IsPaused ) HandleMenu( result ); result = FetchEvent( False ); } return( True ); } static void ProfileExecution() { #ifdef TIME register long start,stop; #else static struct timeval start; static struct timeval stop; register double secs; #endif register Real delta; register int i; delta = TwoPi/ProfCount; printf("Profiling Execution!\n"); #ifdef TIME start = time((time_t *)NULL); #else gettimeofday(&start,(struct timezone *)NULL); #endif for( i=0; i