/* * xbs: an X-Window ball&sticks plotting program. * Copyright (C) 1995 Michael Methfessel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * The author can be contacted as follows: * * Michael Methfessel * methfessel@ihp-ffo.de * Institute for Semiconductor Physics, PO Box 409, * D-15204 Frankfurt (Oder), Germany */ #include #include #include #include #include #include #include #include #include #define W_HEIGHT 450 /* startup size */ #define W_WIDTH 550 #define NAMAX 2000 #define NBMAX 8000 #define NBTMAX 200 #define NSPMAX 50 #define PI 3.1415926 #define MAXRAD 100.0 #define GRAY0 0.5 #define PSFAC 1.42 #define NPOINTS 5 #define NCOL 31 /* max number of colors to be allocated */ #define FONT "8x13" #define LABFONT "6x10" #define SHADOW 5 #define BELL_LEVEL 30 #define SVINP 10 #define FBMAX 70000 /* max for atoms times frames */ #define NFRMAX 8000 /* max num of frames */ /* return codes for interpret_keypress routine */ #define K_NOP 0 #define K_QUIT 1 #define K_REPLOT 2 #define K_RESETUP 3 #define K_UPDATE 4 #define K_READ_MORE 5 #define K_READ_DONE 6 #define K_ANIMATE 7 /* codes for gray modes */ #define G_STD 0 #define G_RAMP 1 #define G_LIGHT 2 struct ballstr { float pos[3]; float rad; float gray; float r,g,b; int col; int special; char lab[21]; }; struct stickstr { int start; int end; float rad; float gray; int col; }; /* ----- global variables ------- */ struct { char lab[21]; float rad; float r,g,b; char cname[81]; int col; float gray; } spec[NSPMAX]; struct { char lab[21]; float pos[3]; float pol[3]; } atom[NAMAX]; struct { char lab1[21]; char lab2[21]; float min; float max; float rad; float r,g,b; char cname[81]; int col; float gray; } bonds [NBTMAX]; /* jkl */ void ms_sleep(); float distance(); float angle(); float torsion(); int natom,nbond; struct ballstr ball[NAMAX]; struct stickstr stick[NBMAX]; float arc[NPOINTS][2],xbot,xtop,ybot,ytop; Display *dpy; Window win; Drawable drw; Pixmap pixmap,bgrmap; GC gc,gcbg,graygc[NCOL],shadowgc,labelgc,labbggc; unsigned long fground, bground, gpx[NCOL]; int screen,depth,ncol; Screen *screenptr; Colormap cmap; float p[NAMAX][3]; int nspec,nbas,nbonds,ngray; int count; int animate; /* jkl */ int msecs=200; /* jkl */ int ipr=10; int igeo,igx,igy, igw,igh; float igs; int midx,midy; float alat,dist,dist0,amp,dalfa,scale,tmat[3][3],radfac,bndfac; float taux,tauy,dtaux,dtauy,taux0,tauy0,bg; float gslope,gz0,light[3]; float center[3]; float frame[3][FBMAX]; char frstr[NFRMAX][81]; int nframe,iframe,saveframe; FILE *outfp; /* for PS output file */ int hardcopy,usepixmap,numbers,grayvalues,wrinfo,fstep,wrhelp; int framephase; int bline,wire,withbonds,recenter,pmode,gmode,shadow,bondnums; int color,autocolor,reverse,coords,stippled; int showaxes; int replot,resetup,startup,chginfo; int num_print; float pr_xoff,pr_yoff; int lnum,xln; char inf[81]="in.bs", outf[81]="Save.bs", prf[81]="Bs.ps"; char inmv[81],prfsave[81],wname[81],curf[81]; char gmsg[101], emsg[101]; char svinput[SVINP][257]; int svline,nsvline=1; /* forward declarations */ void WriteStatus (Drawable draw); void WriteInfo (Drawable draw); void WriteHelp (); /* procedures for graphics */ #define MAXRGB 65535 #define HIGHGRAY 65535 /* top of gray scale */ #define LOWGRAY 0 /* bottom of gray scale */ /* ------- parse_color ------- */ int parse_color (str, rval, gval, bval, gray) char str[]; float *rval, *gval, *bval, *gray; { int isname,i,j,j0,rc; XColor color,exact; float r,g,b; char cname[81]; rc=1; strcpy (cname, str); j0=0; isname=0; for (j=0;j0) cname[j0+1]=0; if (j0>0) str[j0+1]=0; if (XLookupColor (dpy, cmap, cname, &exact, &color)) { r=exact.red / (float) MAXRGB; g=exact.green / (float) MAXRGB; b=exact.blue / (float) MAXRGB; } else { /* printf("parse_color: Cannot look up color <%s>\n", cname); */ r=g=b=1.0; rc=0; } } else { r=b=g=999.9; sscanf (cname, "%f %f %f", &r, &g, &b); if (r>999.0) r=0.0; if (g>999.0) g=r; if (b>999.0) b=r; } if (reverse) { r=1.0-r; g=1.0-g; b=1.0-b; } *rval=r; *gval=g; *bval=b; *gray=(r+g+b)/3.0; /* printf ("parse_color: rgb %.3f %.3f %.3f gray %.3f <%s>\n", *rval, *gval, *bval, *gray, cname); */ return rc; } /* ------- GetColorGC ------- */ int GetColorGC (gpixel) unsigned long gpixel; { int i,j,j0,icol; j0=-1; for (j=0;j=0) { /* printf("GetColorGC: already have pixel %d in slot %d\n",gpixel,j0); */ return j0; } if (ncol>=NCOL) { sprintf(emsg, "no more room for colors.. increase dimension NCOL"); return 0; } /* find a slot and make a graphics context */ icol=ncol; for (j=0;j rgb %.2f %.2f %.2f", spec[i].lab, spec[i].cname, spec[i].r, spec[i].g, spec[i].b); return 0; } if (! parse_color(cname, &spec[i].r, &spec[i].g, &spec[i].b, &spec[i].gray)) { sprintf (emsg, "Cannot identify color <%s>", cname); return 0; } strcpy (spec[i].cname, cname); if (color) { col1.red = spec[i].r*MAXRGB; col1.green = spec[i].g*MAXRGB; col1.blue = spec[i].b*MAXRGB; col2=col1; if (XAllocColor(dpy, cmap, &col1)) gpixel = col1.pixel; else { sprintf(emsg, "Cannot allocate color <%s>", cname); return 0; } icol=spec[i].col; spec[i].col=-1; FreeColorGC (icol); icol=GetColorGC (gpixel); spec[i].col=icol; } } } if (nmatch==0 && (strlen(cname)==0)) { sprintf (emsg, "No species matches \'%s\'", pat); return 0; } f=MAXRGB; sprintf (gmsg, "%s <%s> rgb %.2f %.2f %.2f shown as %.2f %.2f %.2f", list, cname, col2.red/f,col2.green/f,col2.blue/f, col1.red/f,col1.green/f,col1.blue/f); if (nmatch==0) return 0; return 1; } /* ------- SetSmoothGrays --- --- */ void SetSmoothGrays () { int i,allocated[NCOL]; int lastgnum; unsigned long gpixel; XColor color; int g1,g2,gnum; float dg; ngray=21; g1=HIGHGRAY; g2=LOWGRAY; dg=(g2-g1)/(ngray-1.0); lastgnum=0; for (i=0;ingray-1) igray=ngray-1; if (igray<0) igray=0; return graygc[igray]; } } /* ------ showline ------ */ void showline(drawable, x, y, s1, s2, s3) Drawable drawable; int x,y; char s1[],s2[],s3[]; { char sx[1001]; strcpy (sx, s1); strcat (sx, s2); strcat (sx, s3); XFillRectangle(dpy, drawable, gcbg, x, igh-y-9, x+6*strlen(sx), 12); XDrawString (dpy, drawable, labelgc, x, igh-y, sx, strlen(sx)); } /* ------ clearline ------ */ void clearline(drawable, x, y) Drawable drawable; int x,y; { XFillRectangle(dpy, drawable, gcbg, x, igh-y-11, igw-x-20, 14); } /* ------ DrawArrow ------ */ void DrawArrow(x0, y0, x1, y1, rad, str) float x0,y0,x1,y1,rad; char str[]; { int xx1,yy1,xx0,yy0,xx,yy,dd; xx1=midx+PSFAC*x1; yy1=midy-PSFAC*y1; xx0=midx+PSFAC*x0; yy0=midy-PSFAC*y0; xx=0.9*xx0+0.1*xx1; yy=0.9*yy0+0.1*yy1; XDrawLine (dpy, drw, shadowgc, xx, yy, xx1, yy1); XDrawLine (dpy, drw, gc, xx0, yy0, xx1, yy1); xx=xx1+0.3*(xx1-xx0); yy=yy1+0.3*(yy1-yy0)+4; dd=strlen(str)*6; XDrawLine (dpy, drw, labbggc, xx+2-dd/2, yy-4, xx+dd/2-2, yy-4); XDrawString (dpy, drw, labelgc, xx-dd/2, yy, str, strlen(str)); } /* ------ DrawBall ------ */ void DrawBall(gray, col0, x, y, rad) float gray,x,y,rad; int col0; { int xx,yy,rr,icol; GC gcfill; rr=PSFAC*rad; xx=midx+PSFAC*x; yy=midy-PSFAC*y; if (shadow) XDrawArc (dpy, drw, shadowgc, xx-rr, yy-rr, 2*rr, 2*rr, 0, 360*64); if (! wire) { gcfill=ChooseColor(gray,col0); XFillArc (dpy, drw, gcfill, xx-rr, yy-rr, 2*rr, 2*rr, 0, 360*64); } XDrawArc (dpy, drw, gc, xx-rr, yy-rr, 2*rr, 2*rr, 0, 360*64); } /* ------ DrawStick ------ */ void DrawStick(gray, col0, m1, m2) float gray, m1[6], m2[6]; int col0; { int x1,y1,x2,y2,i,igray; float x,y; XPoint pp[NPOINTS*2+1]; GC gcfill; if (bline) { x1=midx+PSFAC*m1[4]; y1=midy-PSFAC*m1[5]; x2=midx+PSFAC*m2[4]; y2=midy-PSFAC*m2[5]; if (shadow) XDrawLine (dpy, drw, shadowgc, x1, y1, x2, y2); XDrawLine (dpy, drw, gc, x1, y1, x2, y2); return; } for (i=0;i=0; i--) if ((str[i]!=' ') && (str[i]!='\n')) { i2=i+1; break; } for (i=i1;i <%s>\n", l, i1, i2, str, str1);*/ } int abbrev (str,ab,nchar) char str[],ab[]; int nchar; { int i,nc; if (strlen(str) > strlen(ab)) return 0; nc=strlen(str); if (nc0) q++; *q = 0; strcat(fid1,ext); } /* ----- match ------- */ int match (str, pat) char str[], pat[]; { char *p,*s; p=pat; s=str; while (*p != 0) { if (*p == '*') { /* found wildcard '*' in pattern */ p++; while (*p == '*') p++; if (*p == 0) return 1; /* trailing '*' matches all */ for (;;) { /* find match to char after '*' */ if (*s == 0) return 0; if ((*s == *p) || (*p == '+')) if (match(s+1,p+1)) return 1; /* ok if rest matches */ s++; } return 0; /* tried all cases but none worked */ } else { /* no wildcard -- char must match */ if (*s == 0) return 0; if ((*p != *s) && (*p != '+')) return 0; s++; } p++; } if (*s != 0) return 0; /* pattern but not string exhausted */ return 1; } /* ----- get_extent ----- */ void get_extent(xx1,xx2,yy1,yy2,zz1,zz2) float *xx1,*xx2,*yy1,*yy2,*zz1,*zz2; { float big,x1,x2,y1,y2,z1,z2; int i; big=1000000; if(nbas==0) big=0; x1=y1=z1=big; x2=y2=z2=-big; for (i=0;ix2) x2=p[i][0]; if (p[i][1]y2) y2=p[i][1]; if (p[i][2]z2) z2=p[i][2]; } *xx1=x1+center[0]; *xx2=x2+center[0]; *yy1=y1+center[1]; *yy2=y2+center[1]; *zz1=z1+center[2]; *zz2=z2+center[2]; } /* ----- atompos: position and radius on paper for an atom --- */ void atompos( float fac, float p[3], float rad, float zp[2], float *zr) { float y[3],q[3],v1[3],v2[3]; float xxx,za1,za2,zb1,zb2,a,b; if (pmode==1) { zp[0]=fac*p[0]; zp[1]=fac*p[1]; *zr=fac*rad; *zr=MAXRAD; if (dist0-p[2]>0) *zr=fac*rad*dist0/(dist0-p[2]); if (*zr > MAXRAD) *zr=MAXRAD; return; } vscal(p, 1.0, q); q[2] = q[2]-dist; vscal(p, 1.0, y); xxx = -sp(y,q)/sp(q,q); vsum(y, q, 1.0, xxx, y); if(sp(y,y)<=1e-3) { y[0]=1.0; y[1]=0.0; y[2]=0.0; } a = -rad*rad / sp(q,q); b = rad*sqrt((1.0+a) / sp(y,y)); vsum(q, y, a, b, v1); vsum(q, y, a, -b, v2); vsum(p, v1, 1.0, 1.0, v1); vsum(p, v2, 1.0, 1.0, v2); za1 = fac*v1[0]*dist / (dist-v1[2]); za2 = fac*v1[1]*dist / (dist-v1[2]); zb1 = fac*v2[0]*dist / (dist-v2[2]); zb2 = fac*v2[1]*dist / (dist-v2[2]); zp[0] = 0.5*(za1+zb1); zp[1] = 0.5*(za2+zb2); *zr = (zb1-za1)*(zb1-za1) + (zb2-za2)*(zb2-za2); *zr = 0.5 * sqrt(*zr); } /* ----- readclusterdata ---- */ int readclusterdata(char infile[]) { FILE *fp; char str[257],token[81]; char xxx [81]; char *p; int l,i,nn; if((fp = fopen (infile,"r")) == NULL) return 0; fgets(str, 257, fp); while(!feof(fp)) { l=strlen(str); str[l+1]='\0'; strcpy(token,"SNOT"); sscanf(str,"%s",token); if (p=strstr(str,"frame")) { if (nframe*nbas>FBMAX) rx("increase internal dimension FBMAX"); if (nframe>NFRMAX) rx("increase internal dimension NFRMAX"); p=p+6; sprintf(frstr[nframe], "%-80s", p); for (i=0;i 0) { if(a[i] > nbas){ sprintf(gmsg, "Atom number %d at position %d is too large",a[i],i+1); return 0; } for(k=0; k< 3; k++) { if(iframe == 0) {atcors[i][k] = atom[a[i]-1].pos[k];} else {atcors[i][k] = frame[k][iframe*nbas+a[i]-1];} } n++; } else break; } if(n == 1) { sprintf(gmsg,"Coordinates X[%d]=%.4f Y[%d]=%.4f Z[%d]=%.4f", a[0], atcors[0][0], a[0], atcors[0][1], a[0], atcors[0][2]); } else if(n == 2) { sprintf(gmsg, "Distance %d:%d is %.4f A", a[0], a[1], distance(atcors[0], atcors[1])); } else if(n == 3) { sprintf(gmsg, "Angle %d:%d:%d is %.4f deg", a[0], a[1], a[2], angle(atcors[0], atcors[1], atcors[2])); } else if(n == 4) { sprintf(gmsg, "Torsion angle %d:%d:%d:%d is %.4f deg", a[0], a[1], a[2], a[3], torsion(atcors[0], atcors[1], atcors[2], atcors[3])); } return 0; } if(!strcmp(token,"spec")) { sscanf(str,"%*s %s %f %n", spec[nspec].lab, &spec[nspec].rad, &n); strip (spec[nspec].cname, str+n); nspec++; if (nspec>NSPMAX) rx("increase internal dimension NSPMAX"); return 2; } if(!strcmp(token,"atom")) { atom[nbas].pol[0]=0; atom[nbas].pol[1]=0; atom[nbas].pol[2]=0; sscanf(str,"%*s %s %f %f %f %f %f %f", atom[nbas].lab, &atom[nbas].pos[0], &atom[nbas].pos[1], &atom[nbas].pos[2], &atom[nbas].pol[0], &atom[nbas].pol[1], &atom[nbas].pol[2]); nbas++; if (nbas>NAMAX) rx("increase internal dimension NAMAX"); return 2; } if(!strcmp(token,"bonds")) { sscanf(str,"%*s %s %s %f %f %f %n", bonds[nbonds].lab1, bonds[nbonds].lab2, &bonds[nbonds].min, &bonds[nbonds].max, &bonds[nbonds].rad, &n); strip (bonds[nbonds].cname, str+n); nbonds++; if (nbonds>NBTMAX) rx("increase internal dimension NBTMAX"); return 2; } if(!strcmp(token,"tmat")) { sscanf(str, "%*s %f %f %f %f %f %f %f %f %f", &tmat[0][0], &tmat[0][1], &tmat[0][2], &tmat[1][0], &tmat[1][1], &tmat[1][2], &tmat[2][0], &tmat[2][1], &tmat[2][2]); return 1; } if(!strcmp(token,"dist") || !strcmp(token,"d")) { sscanf(str, "%*s %f", &dist0); return 1; } if(!strcmp(token,"time")) { sscanf(str, "%*s %d", &msecs); return 1; } if(!strcmp(token,"inc")) {sscanf(str, "%*s %f", &dalfa); return 3;} if(!strcmp(token,"frm")) { sscanf(str, "%*s %d", &nn); if (nn>nframe || nn<1) { sprintf (emsg, "No frame %d available", nn); return 0; } if (iframe==nn-1) return 0; iframe=nn-1; return 2; } if(!strcmp(token,"light")) { light[0]=light[1]=light[2]=0.0; sscanf(str,"%*s %f %f %f", &light[0], &light[1], &light[2]); if (light[0]*light[0]+light[1]*light[1]+light[2]*light[2]<.01) { sprintf (gmsg, "Use standard coloring"); gmode=G_STD;; return 2; } if (color) { sprintf(emsg, "light: only works in b/w mode"); return 0; } gmode=G_LIGHT; return 2; } if(!strcmp(token,"step")) {sscanf(str,"%*s %d", &fstep); return 1;} if(!strcmp(token,"scale")) { sscanf(str,"%*s %f", &scale); scale=scale*igs; return 1; } if(!strcmp(token,"rfac")) {sscanf(str,"%*s %f", &radfac); return 1;} if(!strcmp(token,"bfac")) {sscanf(str,"%*s %f", &bndfac); return 1;} if(!strcmp(token,"amp")) {sscanf(str,"%*s %f", &); return 2;} if(!strcmp(token,"pos")) {sscanf(str,"%*s %f %f", &taux, &tauy); return 1;} if(!strcmp(token,"dpos")) { sscanf(str,"%*s %f", &dtaux); dtauy=dtaux; chginfo=1; return 0;} if(!strcmp(token,"gramp")) { gslope=gz0=0; sscanf(str, "%*s %f %f", &gslope, &gz0); if (gslope*gslope<0.1) { sprintf (gmsg, "Use standard coloring"); gmode=G_STD; return 2; } if (color) { sprintf(emsg, "gramp: only works in b/w mode"); return 0; } gmode=G_RAMP; return 2; } if(!strcmp(token,"switches")) { sscanf(str, "%*s %d %d %d %d %d %d %d %d %d", &usepixmap,&numbers,&grayvalues,&bline,&wire, &withbonds,&recenter,&pmode,&shadow); return 2; } sprintf(emsg,"Undefined command: %s", token); if (startup) printf ("Cannot understand line: %s\n", str); return 0; } /* ----- writeclusterdata ---- */ void writeclusterdata(char outfile[], int svstep, int svrgb) { FILE *fp; char nm[81]; int i,nn,n,nfrm; time_t ltime; char timestr[41]; if((fp = fopen (outfile,"w")) == NULL) { sprintf(emsg, "Cannot open file %s\n", outfile); return;} time(<ime); strcpy (timestr, ctime(<ime)); timestr[24]=0; fprintf (fp, "* Saved %s from %s\n\n", timestr, inf); for (i=0;i1) { strext (nm, outfile, "mv", 1); if((fp = fopen (nm,"w")) == NULL) { sprintf(emsg,"Cannot open file %s\n", nm); return;} nfrm=1; for (i=1;itop) top=sp; if (sp-1) { dis=0.0; for (m=0;m<3;m++) { dd = ball[k].pos[m] - ball[l].pos[m]; dis=dis+dd*dd; } dis=alat*sqrt(dis); if( (dis>=bonds[kb].min) && (dis<=bonds[kb].max) ) { i++; if (i>NBMAX) rx("increase internal dimension NBMAX"); stick[i].start = k; stick[i].end = l; stick[i].rad = bonds[kb].rad; stick[i].gray = bonds[kb].gray; stick[i].col = bonds[kb].col; } } } nbond=i+1; return nbond; } /* ----- duplicate_atoms ---- */ int duplicate_atoms(sh,helpme) float sh[3][6]; int helpme; { int k,l,iv,nbas1,ndup,fr,nn,nn1; float cx,cy,cz; if (helpme) { sprintf (gmsg,"Usage: dup vx vy vz - duplicate shifted by vector"); return 0; } ndup=0; for (iv=0;iv<6;iv++) { cx=sh[0][iv]; cy=sh[1][iv]; cz=sh[2][iv]; if (cx*cx+cy*cy+cz*cz>0.001) ndup++; } if (ndup==0) { sprintf (emsg, "Cannot dup for (0,0,0)"); return 0; } nbas1=nbas*(ndup+1); if (nframe*nbas1>FBMAX) { sprintf(emsg,"Cannot dup, internal dimension FBMAX too small"); return 0; } if (nbas*(ndup+1)>NAMAX) { sprintf(emsg,"Cannot dup, internal dimension NAMAX too small"); return 0; } for (iv=0;iv=0; fr--) { for (k=0;k\n", 1, frstr[0]); if (nframe>1) printf ("frame %-5d <%s>\n", 2, frstr[1]); if (nframe>2) printf ("frame %-5d <%s>\n", nframe, frstr[nframe-1]); return; } /* ----- draw_axes ----- */ void draw_axes () { float e0[3],e1[3],e2[3],z0[2],z1[2],z2[2]; float fac,r0,r1,r2,tx,ty,zz[3]; int m,i,j,i0; tx = (70 -midx)/PSFAC; ty = -(igh-120 -midy)/PSFAC; fac = 30; for (m=0;m<3;m++) { e0[m]=tmat[m][0]; e1[m]=tmat[m][1]; e2[m]=tmat[m][2]; } atompos(fac, e0, 1.0, z0, &r0); atompos(fac, e1, 1.0, z1, &r1); atompos(fac, e2, 1.0, z2, &r2); /* sort vectors (clumsily) back to front */ zz[0]=e0[2]; zz[1]=e1[2]; zz[2]=e2[2]; for (i=0;i<3;i++) { i0=0; if (zz[1] xtop) xtop=zp[k][0]+zr[k]; if (zp[k][1]-zr[k] < ybot) ybot=zp[k][1]-zr[k]; if (zp[k][1]+zr[k] > ytop) ytop=zp[k][1]+zr[k]; } /* printf ("bounds x %.3f %.3f y %.3f %.3f\n", xbot,xtop,ybot,ytop); */ /* ------- start loop over atoms; plot ball first ----- */ for (n=0;n=0) { br = bndfac*stick[ib].rad; bx = zp[kk][0]-zp[k][0]; by = zp[kk][1]-zp[k][1]; xx = sqrt(bx*bx+by*by); if ( xx*xx < 0.0001 ) continue; bx=bx/xx; by=by/xx; vsum(d, p[k], 1.0, -1.0, q1); vsum(d, p[kk], 1.0, -1.0, q2); vsum( p[kk], p[k], 1.0, -1.0, b); cth1 = sp(q1,b) / sqrt(sp(q1,q1)*sp(b,b)); cth2 = -sp(q2,b) / sqrt(sp(q2,q2)*sp(b,b)); th1=acos(cth1); th2=acos(cth2); crit1 = asin(br/rk) * fudgefac; if (crit1<0.0) crit1=0.0; crit2 = asin(br/rkk) * fudgefac; if (crit2<0.0) crit2=0.0; note=0; if(th2-0.5*PI>crit2 && kkk) note=2; /* if(th2-0.5*PI>crit2 && nnn) note=2; */ /* ------- plot a stick ------ */ if (note==1 || note==2) { w = sqrt(rk*rk - br*br); sth1 = sqrt(1.0-cth1*cth1); ww = w*sth1*zr[k]/rk; bb = br*zr[k]/rk; aa = br*cth1*zr[k]/rk; m1[0]=bx*aa; m1[1]=by*aa; m1[2]=-by*bb; m1[3]=bx*bb; m1[4]=zp[k][0]+bx*ww+taux; m1[5]=zp[k][1]+by*ww+tauy; w = sqrt(rkk*rkk-br*br); sth2 = sqrt(1.0-cth2*cth2); ww=w*sth2*zr[kk]/rkk; bb=br*zr[kk]/rkk; aa=br*cth2*zr[kk]/rkk; m2[0]=bx*aa; m2[1]=by*aa; m2[2]=-by*bb; m2[3]=bx*bb; m2[4]=zp[kk][0]-bx*ww+taux; m2[5]=zp[kk][1]-by*ww+tauy; beta=exp(gslope*(0.5*(p[k][2]+p[kk][2])-gz0)*gslope); if (grayvalues) { if (gmode==G_STD) gray = stick[ib].gray; else if (gmode==G_LIGHT) gray=0.5*(ball[k].gray+ball[kk].gray); else if(gmode==G_RAMP) gray=beta*stick[ib].gray+(1-beta)*GRAY0; } else gray=1.0; if (grayvalues && bline && gray>0.7) gray=0.7; if (!grayvalues && bline) gray=0.0; if (grayvalues && wire) gray=0.0; if (bline) gray=0.0; /* overrides... black if lines */ if (ball[k].special) dbond(1.0, m2, m1); else if(ball[kk].special) dbond(1.0, m1, m2); else { if(hardcopy) hardcopy_stick(gray, m1, m2); else /* printf ("draw stick %d col0=%d\n", ib, stick[ib].col); */ DrawStick(gray, stick[ib].col, m1, m2); } /* next part writes bond lengths onto the sticks */ if (bondnums) { bmidx=0.5*(zp[k][0]+zp[kk][0])+taux; bmidy=0.5*(zp[k][1]+zp[kk][1])+tauy; dd=0; for (m=0;m<3;m++) dd=dd+pow(ball[k].pos[m]-ball[kk].pos[m],2); dd=sqrt(dd); sprintf(label, "%.2f", dd); if(hardcopy) hardcopy_label (bmidx, bmidy, label); else LabelBG (bmidx, bmidy, 0.0, 1.0, label); } } } /* if (ib!=0) */ } /* end loop over nn */ } /* end loop over n */ if (showaxes) draw_axes(); } /* ----- do_ConfigureNotify ---- */ int do_ConfigureNotify (eventp) XEvent *eventp; { XConfigureEvent *e = (XConfigureEvent *) eventp; int x1,x2,y1,y2,mmx,mmy,h1,w1,xx; /* x1=midx+PSFAC*(taux+xbot); x2=midx+PSFAC*(taux+xtop); y1=midy+PSFAC*(tauy+ybot); y2=midy+PSFAC*(tauy+ytop); printf ("old area: X %d %d Y %d %d\n", x1,x2,y1,y2); */ mmx=midx; mmy=midy; w1=igw; h1=igh; if ( (e->height!=igh) || (e->width!=igw)) { igw=e->width; igh=e->height; midx=igw/2; midy=igh/2-20; /* make new pixmaps but save contents of bgrmap */ XCopyArea(dpy, bgrmap, pixmap, gc, 0, 0, w1, h1, 0, 0); XFreePixmap (dpy, bgrmap); bgrmap = XCreatePixmap (dpy, win, igw, igh, depth); XFillRectangle(dpy, bgrmap, gcbg, 0, 0, igw, igh); XCopyArea(dpy, pixmap, bgrmap, gc, 0, 0, w1, h1, 0, 0); XFreePixmap (dpy, pixmap); pixmap = XCreatePixmap (dpy, win, igw, igh, depth); if (num_print == 0) { /* normally put back to middle on resize */ taux=taux0=0; tauy=tauy0=0; } else { /* but don't move plot about if building a print */ taux=taux-(midx-mmx)/PSFAC; taux0=taux0-(midx-mmx)/PSFAC; tauy=tauy-(midy-mmy-igh+h1)/PSFAC; tauy0=tauy0-(midy-mmy-igh+h1)/PSFAC; } return 1; } else return 0; } /* ----- close_print ---- */ int close_print(helpme) int helpme; { if (helpme) { sprintf (gmsg,"Usage: close - close current print file"); return 0; } if (num_print==0) { sprintf (emsg, "close: no print file is open"); return; } hardcopy_close(); XFillRectangle(dpy, bgrmap, gcbg, 0, 0, igw, igh); num_print=0; } /* ----- handle_print ---- */ int handle_print(msg1,msg2,helpme) char msg1[], msg2[]; int helpme; { char xx[81]; float x,y,x1,y1,z1,x2,y2,z2; int ix,iy,dd; Drawable drw1; if (helpme) { sprintf (gmsg,"Usage: print [-T] [-t title] [file] - print to PS file"); return 0; } sprintf (gmsg,"Print:"); if (num_print>0 && strcmp(prf,prfsave)) { close_print(0); sprintf (xx, " %s closed,", prfsave); strcat (gmsg, xx); replot=1; } if (num_print==0) { hardcopy_init(prf); sprintf (xx, " %s opened,", prf); strcat (gmsg, xx); pr_xoff=0; pr_yoff=ybot-15; } else { hardcopy_redefine(); } num_print++; strcpy (prfsave,prf); hardcopy=1; bs_transform(natom, ball); bs_kernel(natom, ball, nbond, stick); hardcopy=0; drw=bgrmap; bs_kernel(natom, ball, nbond, stick); if (strlen(msg1)>0) { x=pr_xoff+taux; y=pr_yoff+tauy; hardcopy_label (x, y, msg1); ix=midx+PSFAC*x; iy=midy-PSFAC*y; dd=strlen(msg1)*6; XDrawString (dpy, win, labelgc, ix-dd/2, iy, msg1, strlen(msg1)); XDrawString (dpy, bgrmap, labelgc, ix-dd/2, iy, msg1, strlen(msg1)); } if (strlen(msg2)>0) { x=pr_xoff+taux; y=pr_yoff+tauy-10; hardcopy_label (x, y, msg2); ix=midx+PSFAC*x; iy=midy-PSFAC*y; dd=strlen(msg2)*6; XDrawString (dpy, win, labelgc, ix-dd/2, iy, msg2, strlen(msg2)); XDrawString (dpy, bgrmap, labelgc, ix-dd/2, iy, msg2, strlen(msg2)); } fflush (outfp); sprintf(xx," write(%d) to %s", num_print, prf); strcat (gmsg, xx); } /* ----- update_from_file---- */ int update_from_file () { char msg1[81],msg2[81],str[81],pat[81],w[8][41]; char *p; float sh[3][6],cut[3],cut1,cut2; int i,j,n,rc,nw,svstep,svrgb,helpme; nbas=0; nbonds=0; nspec=0; nframe=1; if (!readclusterdata(inf)) { sprintf (emsg, "Cannot update from file %s", inf); return 0; } sprintf (curf, "%s ", inf); clearline (win, 10, 8); showline (win, 10, 8, "Reading ", inmv, " .. please wait"); XFlush(dpy); sprintf(gmsg,"Updated from %s ", inf); if(readclusterdata(inmv)) { sprintf(gmsg,"Updated from %s and %s", inf, inmv); sprintf(frstr[0], "%s", "start ..\0"); strcat (curf, inmv); } for (i=0;i0) strip(msg2, frstr[iframe]); } else if (w[i][0]=='-') { sprintf (emsg, "print: unknown flag %s", w[i]); return; } else { strext (prf, w[i], "ps", 0); } i++; } handle_print (msg1, msg2, helpme); } } else if (abbrev(w[0],"close",2)) { if (!helpme) sprintf(gmsg, "Print: %s closed after %d write%s", prf, num_print, num_print==1 ? "" : "s"); close_print (helpme); replot=1; } else if (abbrev(w[0],"dup",3)) { for (i=0;i<3;i++) for (j=0;j<6;j++) sh[i][j]=0; sscanf(inp, "%*s %f %f %f %f %f %f %f %f %f %f %f %f", &sh[0][0],&sh[1][0],&sh[2][0],&sh[0][1],&sh[1][1],&sh[2][1], &sh[0][2],&sh[1][2],&sh[2][2],&sh[0][3],&sh[1][3],&sh[2][3], &sh[0][4],&sh[1][4],&sh[2][4],&sh[0][5],&sh[1][5],&sh[2][5]); if (duplicate_atoms (sh,helpme)) resetup=2; } else if (abbrev(w[0],"cut",3)) { cut[0]=cut[1]=cut[2]=cut1=cut2=0; sscanf(inp, "%*s %f %f %f %f %f", &cut[0], &cut[1], &cut[2], &cut1, &cut2); if (cut_atoms (cut, cut1, cut2, helpme)) resetup=2; } else if (abbrev(w[0],"color",3)) { strcpy (pat,""); sscanf(inp, "%*s %s %n", pat, &n); for (i=n;i-1) strcpy (wname, argv[k]); if (igeo & WidthValue) hint.width=igw; else igw=hint.width; if (igeo & HeightValue) hint.height=igh; else igh=hint.height; if (igeo & XValue) hint.x=igx; if (igeo & YValue) hint.y=igy; /* need next line to make +0+0 work */ if ((igeo & XValue) && (hint.x==0) && (hint.y==0)) hint.x=1; if (j==1) { printf ("\nUsage: xbs [flags] id -- ball-and-sticks plotting program\n" "Data is read from files id.bs and id.mv\n" "\nFlags: -geo gg set window geometry \n" " -sc x set scale factor\n" " -t title set window title\n" " -color use color\n" " -bw b/w with smooth grays\n" " -st b/w with stippled grays\n" " -rv reverse colors\n" " -autocolor chose own colors\n" " -hh long help\n" "\nHelp: Enter 'xbs -hh' to get an overview.\n" "For on-line help, press key 'h' for the overview or use\n" "'help ' or ' ?' in the input line for information\n" "on a specific command (including possible options).\n" "Request the input line with key 'i'.\n" ); printf ("\nSettings: geometry %dx%d%+d%+d, scale %.2f,\n" "color %s, autocolor %s, stippled %s, reverse %s\n ", hint.width,hint.height,hint.x,hint.y, igs, yn[color], yn[autocolor], yn[stippled], yn[reverse] ); exit (0); } if (!strstr(inf,".")) strcat(inf, ".bs"); /* ----- read data file ------ */ sprintf (curf,"%s ", inf); nframe=1; strext (inmv, inf, "mv", 1); if (! readclusterdata(inf)) { printf ("Could not open input file %s\n", inf); exit (1); } if (natom<=80) usepixmap=1; /* ----- setup ---- */ dpy = XOpenDisplay (""); if (! dpy) { printf ("Error: could not open display\n"); exit(1); } screen = DefaultScreen (dpy); screenptr = DefaultScreenOfDisplay(dpy); bground = WhitePixel (dpy, screen); fground = BlackPixel (dpy, screen); if ((igeo & XValue) && (igeo & XNegative)) hint.x=igx+WidthOfScreen(screenptr)-hint.width-18; if ((igeo & YValue) && (igeo & YNegative)) hint.y=igy+HeightOfScreen(screenptr)-hint.height-34; hint.flags = PPosition | PSize; win = XCreateSimpleWindow (dpy, DefaultRootWindow(dpy), hint.x, hint.y, hint.width, hint.height, 0, 0, bground); midx=igw/2; midy=igh/2-20; iconmap = XCreateBitmapFromData(dpy, win, bs_icon_bits, bs_icon_width, bs_icon_height); XSetStandardProperties (dpy, win, wname, wname, iconmap, argv, argc, &hint); gc = XCreateGC (dpy, win, 0, 0); XSetBackground (dpy, gc, bground); XSetForeground (dpy, gc, fground); XSelectInput (dpy, win, (KeyPressMask|ExposureMask|StructureNotifyMask)); XMapRaised (dpy, win); drw=win; /* ----- additional setup for graphics ---- */ font=XLoadFont (dpy, FONT); XSetFont (dpy, gc, font); gcbg = XCreateGC (dpy, win, 0, 0); XSetForeground (dpy, gcbg, bground); shadowgc = XCreateGC (dpy, win, 0, 0); XSetLineAttributes (dpy, shadowgc, SHADOW, LineSolid, CapRound, JoinBevel); XSetForeground (dpy, shadowgc, bground); labelgc = XCreateGC (dpy, win, 0, 0); XSetForeground (dpy, labelgc, fground); font=XLoadFont (dpy, LABFONT); XSetFont (dpy, labelgc, font); labbggc = XCreateGC (dpy, win, 0, 0); XSetLineAttributes (dpy, labbggc, 13, LineSolid, CapRound, JoinMiter); XSetForeground (dpy, labbggc, bground); cmap = XDefaultColormap (dpy, screen); for (i=0;i 0) { if(XPending(dpy) > 0) { XNextEvent (dpy, &ev); if((ev.type == ConfigureNotify) || (ev.type == KeyPress)) { animate = 0; goto ProcessEventNow; } } iframe += fstep*framephase; if(animate == 1) { /* frames shown as: 1, 2, ... N, 1, 2 .. */ /* or as N, N-1, N-2, ... 2, 1, N, N-1, N-2 */ if((iframe >= nframe) && (framephase > 0)) { iframe = 0; } else if((iframe < 0) && (framephase < 0)) { iframe = nframe-1; } } else { /* frames shown as: 1, 2, ... N, N-1, N-2, ... 2, 1, 2, 3... */ if((iframe >= nframe) || (iframe < 0)) { framephase *= -1; iframe += 2*framephase*fstep; } } ms_sleep(msecs); resetup = 1; /* [][] */ natom = ball_list (ball, 0); getframe (ball, iframe); nbond = stick_list (ball, stick); replot=1; /* ----- redraw the plot -------- */ rotmat (ixyz, alfa*PI/180.0); bs_transform (natom, ball); if (usepixmap) { drw=pixmap; XCopyArea(dpy, bgrmap, pixmap, gc, 0, 0, igw, igh, 0, 0); } else { drw=win; if (wrinfo) WriteInfo (drw); if (wrhelp>0) WriteHelp (); XCopyArea(dpy, bgrmap, win, gc, 0, 0, igw, igh, 0, 0); } showline(win, 10, 8, "Busy ", " "," "); bs_kernel(natom, ball, nbond, stick); if (startup) showline(win, 10, 8, "Reading ", inmv, " .."); WriteStatus (drw); if (wrinfo) WriteInfo (drw); if (wrhelp>0) WriteHelp (); if (usepixmap) XCopyArea(dpy, pixmap, win, gc, 0, 0, igw, igh, 0, 0); if (startup) { showline(win, 10, 8, "Reading ", inmv, " .. please wait"); XFlush(dpy); k=nframe; if (readclusterdata(inmv)) { sprintf(frstr[0], "%s", "start ..\0"); sprintf (gmsg, "%d frames were read from %s", nframe-k, inmv); strcat (curf, inmv); WriteStatus (win); } else sprintf (gmsg, "No frames in %s", inmv); startup=0; } if (! usepixmap) XCopyArea(dpy, win, pixmap, gc, 0, 0, igw, igh, 0, 0); showline(win, 10, 8, "Done ", ""," "); /* Discard extra keypress events so that rotation stops after key is released. Leave one for smooth motion. */ i=0; while (XCheckTypedEvent(dpy, KeyPress, &ev1)) {i=1;} if (i==1) XPutBackEvent(dpy, &ev1); /* [][] */ } } /* end of jkl mess for a while */ ProcessEventNow: ixyz=0; replot=resetup=chginfo=0; strcpy (gmsg, ""); strcpy (emsg, ""); switch (ev.type) { case Expose: if (ev.xexpose.count == 0) { if(!startup) { XCopyArea(dpy, pixmap, win, gc, 0, 0, igw, igh, 0, 0); if (inpmode) { clearline (win, 10, 8); showline (win, 10, 8, "Input: ", input, "_ "); } if (wrhelp>0) WriteHelp (); } else replot=1; } break; case ConfigureNotify: if (do_ConfigureNotify (&ev)) replot=1; if (startup) replot=0; break; /* ----- process keypress events ----- */ case KeyPress: strcpy (gmsg, ""); strcpy (emsg, ""); keytype=interpret_keypress (&ev, &inpmode, input, &ixyz, &alfa); switch (keytype) { case K_QUIT: finished = 1; break; case K_REPLOT: replot=1; break; case K_RESETUP: resetup=1; break; case K_READ_MORE: clearline (win, 10, 8); showline (win, 10, 8, "Input: ", input, "_ "); break; case K_READ_DONE: clearline(win, 10, 8); if (strlen(input)>0) { for (k=SVINP-1; k>1; k--) strcpy(svinput[k],svinput[k-1]); strcpy(svinput[1],input); nsvline++; } interpret_input (input); break; case K_UPDATE: update_from_file(); break; } break; } /* switch (ev.type) */ /* ----- repeat the setup steps ------- */ if (resetup) { natom = ball_list (ball, 0); getframe (ball, iframe); nbond = stick_list (ball, stick); replot=1; } /* ----- redraw the plot -------- */ if (replot) { rotmat (ixyz, alfa*PI/180.0); bs_transform (natom, ball); if (usepixmap) { drw=pixmap; XCopyArea(dpy, bgrmap, pixmap, gc, 0, 0, igw, igh, 0, 0); } else { drw=win; if (wrinfo) WriteInfo (drw); if (wrhelp>0) WriteHelp (); XCopyArea(dpy, bgrmap, win, gc, 0, 0, igw, igh, 0, 0); } showline(win, 10, 8, "Busy ", " "," "); bs_kernel(natom, ball, nbond, stick); if (startup) showline(win, 10, 8, "Reading ", inmv, " .."); WriteStatus (drw); if (wrinfo) WriteInfo (drw); if (wrhelp>0) WriteHelp (); if (usepixmap) XCopyArea(dpy, pixmap, win, gc, 0, 0, igw, igh, 0, 0); if (startup) { showline(win, 10, 8, "Reading ", inmv, " .. please wait"); XFlush(dpy); k=nframe; if (readclusterdata(inmv)) { sprintf(frstr[0], "%s", "start ..\0"); sprintf (gmsg, "%d frames were read from %s", nframe-k, inmv); strcat (curf, inmv); WriteStatus (win); } else sprintf (gmsg, "No frames in %s", inmv); startup=0; } if (! usepixmap) XCopyArea(dpy, win, pixmap, gc, 0, 0, igw, igh, 0, 0); showline(win, 10, 8, "Done ", ""," "); /* Discard extra keypress events so that rotation stops after key is released. Leave one for smooth motion. */ i=0; while (XCheckTypedEvent(dpy, KeyPress, &ev1)) {i=1;} if (i==1) XPutBackEvent(dpy, &ev1); } /* ----- handle messages, update info if needed -------- */ if (strlen(emsg)>0) { clearline (win, 10, 8); showline(win, 10, 8, "+++ ", emsg, ""); showline(pixmap, 10, 8, "+++ ", emsg, ""); XBell (dpy, BELL_LEVEL); } else if (strlen(gmsg)>0) { clearline (win, 10, 8); showline(win, 10, 8, gmsg, "", ""); showline(pixmap, 10, 8, gmsg, "", ""); } if ( (!replot) && wrinfo && chginfo) WriteInfo (win); } /* while */ /* ----- clean up and exit -------- */ if (num_print>0) hardcopy_close(); XFreeGC (dpy, gc); XDestroyWindow (dpy, win); XCloseDisplay (dpy); } /* ------- intepret_keypress subroutine ------ */ int interpret_keypress (XEvent *ev, int *inpmode, char input[], int *ixyz, float *alfa) { int count,l; char buff[8],msg[81]; unsigned int state; KeySym key; state = ev->xkey.state; count = XLookupString (&ev->xkey, buff, 8, &key, 0); if(state != 0) { /* jkl some translations for keypad keys */ if(key==XK_Up) {key=XK_KP_8;} else if(key==XK_Down) {key=XK_KP_2;} else if(key==XK_Right) {key=XK_KP_6;} else if(key==XK_Left) {key=XK_KP_4;} } if(key==XK_R7) {key=XK_KP_7;} if(key==XK_Home) {key=XK_KP_7;} if(key==XK_R6) {key=XK_KP_Multiply;} if(key==XK_KP_Subtract) {key=XK_minus;} if(key==XK_KP_Add) {key=XK_plus;} if(key==XK_F26) {key=XK_KP_Multiply;} if(key==XK_F28) {key=XK_KP_8;} if(key==XK_F27) {key=XK_KP_7;} if(key==XK_F30) {key=XK_KP_4;} if(key==XK_F34) {key=XK_KP_2;} if(key==XK_F32) {key=XK_KP_6;} if(*inpmode) { l=strlen(input); if (key==XK_Up) { if (svline==0) strcpy (svinput[0], input); if (svline0) svline--; strcpy (input, svinput[svline]); return K_READ_MORE; } if (key==XK_Down) {strcpy (input, ""); return K_READ_MORE; } if (key==XK_Return) { *inpmode=0; return K_READ_DONE; } if (key==XK_BackSpace || key==XK_Left) { if(l>0) input[l-1]='\0'; return K_READ_MORE; } if (count>0) {input[l]=buff[0]; input[l+1]='\0';} return K_READ_MORE; } if (key==XK_bracketright) { if (iframe==nframe-1) { sprintf(gmsg,"Last frame"); return K_NOP; } iframe=iframe+fstep; if (iframe>=nframe) iframe=nframe-1; return K_RESETUP; } /* begin jkl mess */ if (key==XK_A) { /* start animation 1,2,...N,1,2 */ iframe = 0; if(animate > 0) { animate = 0; } else { animate = 1; } return K_RESETUP; } if(key==XK_C) { /* start animation 1,2, ..., N,N-1,N-2, .. 3,1,2,3...*/ iframe = 0; if(animate > 0) { animate = 0; } else { animate = 2; } return K_RESETUP; } if(key==XK_less) { sprintf(gmsg, "Animate counterclockwise"); framephase = -1; return K_NOP; } if(key==XK_greater) { sprintf(gmsg, "Animate clockwise"); framephase = 1; return K_NOP; } /* end jkl mess */ if (key==XK_bracketleft) { if (iframe==0) {sprintf(gmsg,"First frame"); return K_NOP; } iframe=iframe-fstep; if (iframe<=0) iframe=0; return K_RESETUP; } if (key==XK_backslash) { saveframe=iframe; sprintf(gmsg,"Marked frame %d", saveframe+1); return K_NOP; } if (key==XK_bar) { if (saveframe==-99) {sprintf(emsg,"No frame was marked"); return K_NOP; } if (saveframe<0 || saveframe>=nframe) { sprintf(emsg,"Marked frame %d does not exist", saveframe+1); return K_NOP; } if (iframe==saveframe) {sprintf(gmsg,"Already at frame %d", saveframe+1); return K_NOP; } iframe=saveframe; sprintf(gmsg,"Go back to frame %d", saveframe+1); return K_RESETUP; } if (key==XK_braceleft) {iframe=0; return K_RESETUP; } if (key==XK_braceright) {iframe=nframe-1; return K_RESETUP; } if (key==XK_Q) return K_QUIT; if (key==XK_U) return K_UPDATE; if (key==XK_h) { wrhelp=1-wrhelp; return K_REPLOT;} if (key==XK_i) {strcpy(input, ""); *inpmode = 1; svline=0; return K_READ_MORE; } *alfa=0; *ixyz=0; if (key==XK_Right) {*alfa = dalfa; *ixyz=1; return K_REPLOT;} if (key==XK_Left) {*alfa = -dalfa; *ixyz=1; return K_REPLOT;} if (key==XK_Up) {*alfa = -dalfa; *ixyz=2; return K_REPLOT;} if (key==XK_Down) {*alfa = dalfa; *ixyz=2; return K_REPLOT;} if (key==XK_comma) {*alfa = dalfa; *ixyz=3; return K_REPLOT;} if (key==XK_period) {*alfa = -dalfa; *ixyz=3; return K_REPLOT;} if (key==XK_p) {pmode++; if (pmode==3) pmode=0; return K_REPLOT;} if (key==XK_P) {pmode--; if (pmode==-1) pmode=2; return K_REPLOT;} if (key==XK_d) {dist0 = dist0*1.05 ; return K_REPLOT;} if (key==XK_D) {dist0 = dist0/1.05 ; return K_REPLOT;} if (key==XK_r) {return K_REPLOT;} if (key==XK_plus || key==XK_KP_Add) {scale = scale*1.05; return K_REPLOT;} if (key==XK_minus || key==XK_KP_Subtract) {scale = scale/1.05; return K_REPLOT;} if (key==XK_KP_6) {taux = taux + dtaux; return K_REPLOT;} if (key==XK_KP_4) {taux = taux - dtaux; return K_REPLOT;} if (key==XK_KP_8) {tauy = tauy + dtauy; return K_REPLOT;} if (key==XK_KP_2) {tauy = tauy - dtauy; return K_REPLOT;} if (key==XK_KP_7) {taux = taux0; tauy = tauy0; return K_REPLOT;} if (key==XK_KP_Multiply) { taux0 = taux; tauy0 = tauy; sprintf(gmsg, "New home position: %.2f %.2f", taux0, tauy0); chginfo=1; return K_NOP; } if (key==XK_l) { bline=1-bline; if (withbonds) return K_REPLOT; chginfo=1; if (bline) sprintf (gmsg, "Bonds as lines "); else sprintf (gmsg, "Bonds as cylinders "); return K_NOP; } if (key==XK_s) { shadow=1-shadow; return K_REPLOT; } if (key==XK_a) { showaxes=1-showaxes; return K_REPLOT; } if (key==XK_w) { wire=1-wire; return K_REPLOT; } if (key==XK_x) { chginfo=1; usepixmap=1-usepixmap; if(usepixmap) sprintf (gmsg, "Draw to pixmap buffer"); else sprintf (gmsg, "Draw to screen"); chginfo=1; return K_NOP; } if (key==XK_space) {wrinfo=1-wrinfo; return K_REPLOT; } if (key==XK_b) { withbonds=1-withbonds; return K_REPLOT; } if (key==XK_n) { numbers=numbers+1; if (numbers==3) numbers=0; return K_REPLOT; } if (key==XK_c) { coords=1-coords; return K_REPLOT; } if (key==XK_N) { bondnums=1-bondnums; return K_REPLOT;} if (key==XK_g) { grayvalues=1-grayvalues; return K_REPLOT;} return K_NOP; } /* ------- wln ----------------- */ void wln (char x[]) { int xx; if (!startup) { xx=xln; if (xx<1) xx=1; XDrawString (dpy, drw, labelgc, xx, 10*lnum, x, strlen(x)); lnum++; } else printf ("%s\n", x); } /* ------- WriteHelp ----------------- */ void WriteHelp () { lnum=1; /* commands */ xln=igw-250; wln("COMMANDS for input line:"); wln(" help cmd - on-line help"); wln(" inc degrees - rotation increment"); wln(" time milisecs - frame duration"); wln(" tell ijkl - tell geometry"); wln(" pos x y - set position"); wln(" dpos dxy - shift increment"); wln(" dist d - set distance"); wln(" rfac fac - scale all radii"); wln(" bfac fac - scale all bonds"); wln(" scale fac - scale plot"); wln(" gramp slope mid - gray ramp"); wln(" light x y z - light direction"); wln(" step n - set frame step"); wln(" dup x y z - duplicate"); wln(" cut x y z a b - planar cut"); wln(" frm n - go to frame"); wln(" color pat cname - query or set color"); wln(" save fname - save data"); wln(" update fname - update from file"); wln(" print fname - postscript output"); wln(" close - close print file"); /* input */ xln=igw-230; wln(" "); wln("INPUT data format:"); wln(" atom label x y z "); wln(" spec label radius color"); wln(" bonds lab1 lab2 min max radius color"); wln(" frame str x1 .. - add frame"); wln(" tmat t1 .. t9 - viewpoint"); wln("Also COMMANDS which set parameters"); /* keys */ lnum = 1; xln=10; wln("KEYS (KP=Keypad):"); wln(" i activate input line"); wln(" h help"); wln(" space info"); wln(" cursor rotate R/L, U/D"); wln(" , . rotate in plane"); wln(" + - zoom"); wln(" KP 8642 shift plot"); wln(" KP 7 shift home"); wln(" KP * set home"); wln(" r redraw"); wln(" n atom numbers"); wln(" c coordinates"); wln(" N bond lengths"); wln(" w wire mode"); wln(" g gray/bw"); wln(" b bonds"); wln(" l cylinders/lines"); wln(" p perspective"); wln(" a show axes"); wln(" s line shadows"); wln(" x pixmap buffer"); wln(" d D distance"); wln(" [ ] step frames fw/bk"); wln(" A animate 1,2,..N,1,2"); wln(" C animate 1,2,..N,N-1.."); wln(" < > animate back or forward"); wln(" { } first/last frame"); wln(" \\ | mark/goto frame"); wln(" U update from file"); wln(" Q quit"); } /* ------- WriteInfo ----------------- */ void WriteInfo (Drawable draw) { int i; float x1,x2,y1,y2,z1,z2; char str[201],stt[201]; char gmd[3][8] = {"std","ramp","light"}; get_extent(&x1,&x2,&y1,&y2,&z1,&z2); if (natom==1) sprintf(str,"%d atom, ", natom); else sprintf(str,"%d atoms, ", natom); if (nbond==1) sprintf(stt,"%d bond ", nbond); else sprintf(stt,"%d bonds", nbond); showline(draw, 10, igh-20, "", str, stt); sprintf(str, "extent x %.2f to %.2f, y %.2f to %.2f, z %.2f to %.2f", x1,x2,y1,y2,z1,z2); showline(draw, 10, igh-30, "", str, ""); sprintf(str, "tmat %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f", tmat[0][0], tmat[0][1], tmat[0][2], tmat[1][0], tmat[1][1], tmat[1][2], tmat[2][0], tmat[2][1], tmat[2][2]); showline(draw, 10, igh-40, "", str, ""); sprintf(str, "dist %.2f, scale %.2f, rfac %.2f, bfac %.2f", dist0,scale,radfac,bndfac); showline(draw, 10, igh-50, "", str, ""); sprintf(str, "gmode %s, ramp,slope %.2f %.2f, light %.2f %.2f %.2f", gmd[gmode], gslope, gz0, light[0],light[1],light[2]); showline(draw, 10, igh-60, "", str, ""); sprintf(str, "pos (%.1f,%.1f), dpos %.1f, home (%.1f,%.1f)", taux, tauy, dtaux, taux0, tauy0); showline(draw, 10, igh-70, "", str, ""); sprintf(str, "color %d, reverse %d, stippled %d, pixmap %d, gray %d, " "bonds %d, lines %d", color, reverse, stippled, usepixmap, grayvalues, withbonds, bline); showline(draw, 10, igh-80, "", str, ""); sprintf(str, "input %s %s, save %s, print %s, nprint=%d", inf,inmv,outf,prf,num_print); showline(draw, 10, igh-90, "", str, ""); } /* ------- WriteStatus ----------------- */ void WriteStatus (Drawable draw) { char pers[3][8] = {"off","pseudo","true"}; char str[201]; sprintf(str," %5.2f %5.2f %5.2f inc=%.1f" " d=%.2f p=%s", tmat[2][0],tmat[2][1],tmat[2][2], dalfa, dist0, pers[pmode]); showline(draw, 10, 20, "View:", str, ""); sprintf(str,"Frame %3d of %d (step %d) <%s>", iframe+1, nframe, fstep, frstr[iframe]); showline(draw, 10, 44, "Files: ", curf, ""); showline(draw, 10, 32, str, "", ""); }