/*************************************************************************** * RasMol 2.7.1 * * * * RasMol * * Molecular Graphics Visualisation Tool * * 22 June 1999 * * * * Based on RasMol 2.6 by Roger Sayle * * Biomolecular Structures Group, Glaxo Wellcome Research & Development, * * Stevenage, Hertfordshire, UK * * Version 2.6, August 1995, Version 2.6.4, December 1998 * * Copyright (C) Roger Sayle 1992-1999 * * * * and Based on Mods by Arne Mueller * * Version 2.6x1, May 1998 * * Copyright (C) Arne Mueller 1998 * * * * Version 2.7.0, 2.7.1 Mods by Herbert J. Bernstein * * Bernstein + Sons, P.O. Box 177, Bellport, NY, USA * * yaya@bernstein-plus-sons.com * * 2.7.0 March 1999, 2.7.1 June 1999 * * Copyright (C) Herbert J. Bernstein 1998-1999 * * * * Please read the file NOTICE for important notices which apply to this * * package. If you are not going to make changes to RasMol, you are not * * only permitted to freely make copies and distribute them, you are * * encouraged to do so, provided you do the following: * * * 1. Either include the complete documentation, especially the file * * NOTICE, with what you distribute or provide a clear indication * * where people can get a copy of the documentation; and * * * 2. Please give credit where credit is due citing the version and * * original authors properly; and * * * 3. Please do not give anyone the impression that the original * * authors are providing a warranty of any kind. * * * * If you would like to use major pieces of RasMol in some other program, * * make modifications to RasMol, or in some other way make what a lawyer * * would call a "derived work", you are not only permitted to do so, you * * are encouraged to do so. In addition to the things we discussed above, * * please do the following: * * * 4. Please explain in your documentation how what you did differs * * from this version of RasMol; and * * * 5. Please make your modified source code available. * * * * This version of RasMol is not in the public domain, but it is given * * freely to the community in the hopes of advancing science. If you make * * changes, please make them in a responsible manner, and please offer us * * the opportunity to include those changes in future versions of RasMol. * ***************************************************************************/ /* rasmol.c */ #ifndef sun386 #include #endif #include #include #include #include #include #define RASMOL #include "rasmol.h" #include "graphics.h" #include "molecule.h" #include "infile.h" #include "abstree.h" #include "transfor.h" #include "cmndline.h" #include "command.h" #include "render.h" #include "repres.h" #include "pixutils.h" #include "outfile.h" #ifdef esv #include #else #include #endif #ifdef PROFILE #include #ifndef TIME #include #else #include #endif /* TIME */ #endif /* PROFILE */ #ifdef TERMIOS #include #include #include #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 IsIdentChar(x) ((isalnum(x))||((x)=='_')||((x)=='$')) #define TwoPi 2.0*PI /* Either stdout or stderr */ #define OutFp stdout #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 static struct termios OrigTerm; static struct termios IntrTerm; static struct timeval TimeOut; static fd_set OrigWaitSet; static fd_set WaitSet; static int WaitWidth; static int FileNo; #ifdef SOCKETS /* Supported Protocols */ #define ProtoRasMol 0x01 #define AMNone 0x00 #define AMPickAtom 0x01 #define AMPickNumber 0x02 #define AMSelectCount 0x04 #define AMMolName 0x08 #define AMPickCoord 0x10 typedef struct { int bitmask; char *name; } AdviseType; static AdviseType AdviseMap[ItemCount] = { { AMPickAtom, "Pick" }, /* AdvPickAtom */ { AMPickNumber, "PickNo" }, /* AdvPickNumber */ { AMSelectCount, "Count" }, /* AdvSelectCount */ { AMMolName, "Name" }, /* AdvName */ { AMNone, "Ident" }, /* AdvIdent */ { AMNone, "Class" }, /* AdvClass */ { AMNone, "Image" }, /* AdvImage */ { AMPickCoord, "PickXYZ" } /* AdvPickCoord */ }; static char AdviseBuffer[256]; static int AdviseLen; typedef struct { int protocol; int socket; int advise; } IPCConv; #define MaxIPCConvNum 8 static IPCConv IPCConvData[MaxIPCConvNum]; static int ServerPort; static int UseSockets; static int SocketNo; #endif /* SOCKETS */ #endif /* TERMIOS */ static int InitialWide; static int InitialHigh; static char *FileNamePtr; static char *ScriptNamePtr; static int LabelOptFlag; static int FileFormat; static int ProfCount; static int LexState; /*=======================*/ /* Function Prototypes */ /*=======================*/ static int HandleEvents( int ); extern int ProcessCommand( void ); void WriteChar( int ch ) { putc(ch,OutFp); } void WriteString( char *ptr ) { fputs(ptr,OutFp); } static void ResetTerminal( void ) { #ifdef SOCKETS register int i; #endif #ifdef TERMIOS if( isatty(FileNo) ) tcsetattr(FileNo, TCSANOW, &OrigTerm); #endif #ifdef SOCKETS if( UseSockets ) { close(SocketNo); for( i=0; i= WaitWidth ) WaitWidth = socket+1; IPCConvData[i].protocol = ProtoRasMol; IPCConvData[i].socket = socket; IPCConvData[i].advise = AMNone; return( True ); } close( socket ); return( False ); } static void CloseIPCConnection( int conv ) { FD_CLR(IPCConvData[conv].socket,&OrigWaitSet); close( IPCConvData[conv].socket ); IPCConvData[conv].protocol = 0; } static int CaseInsensitiveCompare( char *ptr1, char *ptr2 ) { register unsigned char *rptr1; register unsigned char *rptr2; register unsigned char c1; register unsigned char c2; rptr1 = (unsigned char*)ptr1; rptr2 = (unsigned char*)ptr2; do { c1 = ToUpper(*rptr1++); c2 = ToUpper(*rptr2++); } while( c1 && (c1==c2) ); return c1 - c2; } static int IsIPCAdviseRequest( char *ptr, int conv ) { auto char item[34]; register char *dst; register char *src; register int i,ch; register int flag; if( !strncmp(ptr,"Advise:",7) ) { src = ptr+7; flag = True; } else if( !strncmp(ptr,"Unadvise:",9) ) { src = ptr+9; flag = False; } else return False; while( *src ) { ch = *src++; if( isspace(ch) ) continue; if( isalpha(ch) ) { dst = item; *dst++ = ch; while( IsIdentChar(*src) ) { if( dst < item+32 ) { *dst++ = *src++; } else src++; } *dst = '\0'; for( i=0; i 0 ) { buffer[len] = '\0'; src = dst = buffer; while( (ch = *src++) ) if( (ch>=' ') && (ch<='~') ) *dst++ = ch; *dst = '\0'; if( !IsIPCAdviseRequest(buffer,conv) ) { result = ExecuteIPCCommand(buffer); if( result == IPC_Exit ) { CloseIPCConnection( conv ); } else if( result == IPC_Quit ) RasMolExit(); } } else CloseIPCConnection( conv ); } #endif /* SOCKETS */ static void InitTerminal( 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) ) { tcgetattr(FileNo, &OrigTerm); IntrTerm = OrigTerm; IntrTerm.c_iflag |= IGNBRK|IGNPAR; IntrTerm.c_iflag &= ~(BRKINT|PARMRK|INPCK|IXON|IXOFF); IntrTerm.c_lflag &= ~(ICANON|ISIG|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 tcsetattr(FileNo,TCSANOW,&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( void ) { #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, (fd_set*)NULL, (fd_set*)NULL, &TimeOut ); #endif #ifdef SOCKETS if( UseSockets ) { if( FD_ISSET(SocketNo,&WaitSet) ) { OpenIPCConnection( 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(SphereFlag); DisableWireframe(); SetRibbonStatus(False,0,0); DisableBackbone(); ReDrawFlag |= RFRefresh; break; case(5): /* Ball & Stick */ SetRadiusValue(120, SphereFlag); 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; case(9): /* Model */ ScaleColourAttrib( ModelAttr ); ReDrawFlag |= RFColour; break; case(10): /* Alt */ ScaleColourAttrib( AltAttr ); 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( void ) { if( !UseSlabPlane ) { ReDrawFlag &= ~RFTransZ|RFSlab; } else ReDrawFlag &= ~RFTransZ; 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; } } #ifdef SOCKETS static void PrepareIPCAdviseItem( int item ) { register char *src, *dst; register int i,flag; dst = AdviseBuffer; src = AdviseMap[item].name; while( *src ) *dst++ = *src++; *dst++ = ':'; *dst++ = ' '; switch( item ) { case(AdvPickAtom): if( QAtom ) { src = Residue[QGroup->refno]; flag = False; for( i=0; i<3; i++ ) if( (src[i]!=' ') && !isalpha(src[i]) ) flag = True; if( flag ) *dst++ = '['; for( i=0; i<3; i++ ) if( src[i]!=' ' ) *dst++ = src[i]; if( flag ) *dst++ = ']'; sprintf(dst,"%d",QGroup->serno); for( dst=AdviseBuffer; *dst; dst++ ); if( QChain->ident!=' ' ) { if( isdigit(QChain->ident) ) *dst++ = ':'; *dst++ = QChain->ident; } *dst++ = '.'; src = ElemDesc[QAtom->refno]; for( i=0; i<4; i++ ) if( src[i]!=' ' ) *dst++ = src[i]; } *dst++ = '\n'; *dst = '\0'; break; case(AdvPickNumber): if( !QAtom ) { *dst++ = '\n'; *dst = '\0'; } else sprintf(dst,"%ld\n",(long)QAtom->serno); break; case(AdvSelectCount): sprintf(dst,"%ld\n",(long)SelectCount); break; case(AdvName): src = Info.moleculename; while( *src ) *dst++ = *src++; *dst++ = '\n'; *dst = '\0'; break; case(AdvPickCoord): if( !QAtom ) { *dst++ = '\n'; *dst = '\0'; } else sprintf( dst, "%ld\t%ld\t%ld\n", (long)QAtom->xorg, (long)QAtom->yorg, (long)QAtom->zorg); break; default: *dst++ = '\n'; *dst = '\0'; break; } AdviseLen = strlen(AdviseBuffer)+1; } #endif void AdviseUpdate( int item ) { #ifdef SOCKETS register int mask; register int i; if( UseSockets ) { mask = AdviseMap[item].bitmask; if( !mask ) return; AdviseLen = 0; for( i=0; i