ftp.nice.ch/pub/next/science/chemistry/MolViewer.0.9.s.tar.gz#/MolViewer/Inspector.m

This is Inspector.m in view mode; [Download] [Up]

/* Inspector.m - Copyright 1993  Steve Ludtke */
/* Nothing too exciting here. This just acts as a connection between */
/* the inspector panel and the rest of the program. Most of the */
/* actual work is done elsewhere */
/* No comments here, see Inspector.h for brief descriptions */

#import "Mtypes.h"
#import "Inspector.h"
#import "MolObj.h"
#import "SelectView.h"
#import "AminoView.h"
#import "ctype.h"

extern ACID acid[AADEF];

@implementation Inspector

- startup:(Molecule *)Mol :(int)Nmol :(struct ELINFO *)Elinfo
{
mol=Mol;
nmol=Nmol;
elinfo=Elinfo;
aminoIns=[aminoIns contentView];
atabIns=[atabIns contentView];
atomIns=[atomIns contentView];
mode= -1;
nlist=nsel=0;
size=1.3;
list=NULL;
a_modsel=0;
a_mod[0].nsel=a_mod[1].nsel=a_mod[2].nsel=0;
return self;
}

-update:(int)Nmol :(int)level
{
nmol=Nmol;
if (nmol==0) {
	[[abcount cellAt:0 :0] setStringValue:""];
	[[abcount cellAt:1 :0] setStringValue:""];
}
else {
	[[abcount cellAt:0 :0] setIntValue:mol[0].numa];
	[[abcount cellAt:1 :0] setIntValue:mol[0].numlb];
}

if (level>U_BONDS||mode==-1) [self a_insp:self];
else if (mode==1) [self m_upd:self];
/*else if (mode==2) [self   :self];*/
return self;
}

-newMol
{
mode= -1;
return self;
}

- a_bondAng:sender
{
float d;
char s[80];
int i,n[3];

if (nsel!=3) { [molobj error:"Select 3 atoms first." :NO]; return self;}

for (i=0; i<3; i++) n[i]=list[i].stab;

d=[molobj bondAng:n[0] :n[1] :n[2]]*180.0/M_PI;

for (i=0; i<2; i++) {
	if (mol[0].atom[n[i]].bnd[0]!=n[i+1]&&mol[0].atom[n[i]].bnd[1]!=n[i+1]&& mol[0].atom[n[i]].bnd[2]!=n[i+1]&&mol[0].atom[n[i]].bnd[3]!=n[i+1]) break;
}
if (i==2) sprintf(s,"Angle=%-5.2f deg",d);
else sprintf(s,"Nonbonded, angle=%5.2f",d);

[molobj error:s :NO];
return self;
}

- a_bondLen:sender
{
int n,n1;
float d;
char s[80];

if (nsel!=2) { [molobj error:"Select 2 atoms first." :NO]; return self;}
n=list[0].stab;
n1=list[1].stab;

d=sqrt(SQR(mol[0].coord[n][0]-mol[0].coord[n1][0])+SQR(mol[0].coord[n][1]-mol[0].coord[n1][1])+SQR(mol[0].coord[n][2]-mol[0].coord[n1][2]));

if (mol[0].atom[n].bnd[0]!=n1&&mol[0].atom[n].bnd[1]!=n1&& mol[0].atom[n].bnd[2]!=n1&&mol[0].atom[n].bnd[3]!=n1) {
	sprintf(s,"Nonbonded distance=%4.2f†",d);
}
else sprintf(s,"Distance=%4.2f†",d);

[molobj error:s :NO];
return self;
}

- a_dihedral:sender
{
float d;
char s[80];
int i,n[4];

if (nsel!=4) { [molobj error:"Select 4 atoms first" :NO]; return self;}

for (i=0; i<4; i++) n[i]=list[i].stab;

d=[molobj dihedral:n[0] :n[1] :n[2] :n[3]]*180.0/M_PI;

for (i=0; i<3; i++) {
	if (mol[0].atom[n[i]].bnd[0]!=n[i+1]&&mol[0].atom[n[i]].bnd[1]!=n[i+1]&& mol[0].atom[n[i]].bnd[2]!=n[i+1]&&mol[0].atom[n[i]].bnd[3]!=n[i+1]) break;
}
if (i==3) sprintf(s,"dihedral=%-5.2f deg",d);
else sprintf(s,"nonbonded, angle=%5.2f",d);

[molobj error:s :NO];
return self;
}

- a_setModSel:sender
{
a_modsel=[sender selectedRow];

[a_select selectAry:a_mod[a_modsel].nsel :a_mod[a_modsel].sel];
[self a_setupMod];
return self;
}

-a_setupMod
{
int n,n1,n2,n3;
float d;
char s[80];

n=a_mod[a_modsel].sel[0];
n1=a_mod[a_modsel].sel[1];
n2=a_mod[a_modsel].sel[2];
n3=a_mod[a_modsel].sel[3];

switch (a_mod[a_modsel].nsel) {
case 2:
	d=sqrt(SQR(mol[0].coord[n][0]-mol[0].coord[n1][0])+SQR(mol[0].coord[n][1]-mol[0].coord[n1][1])+SQR(mol[0].coord[n][2]-mol[0].coord[n1][2]));
	[[a_modT cellAt:a_modsel :0] setFloatValue:d];
	[[[[a_modS cellAt:a_modsel :0] setMinValue:d*.6] setMaxValue:d*1.4] setFloatValue:d];
	if ([molobj bonded:n :n1]) sprintf(s,"len %d-%d",n,n1);
	else sprintf(s,"NB len %d %d",n,n1);
	[[a_modT2 cellAt:a_modsel :0] setStringValue:s];
	break;
case 3:
	d=[molobj bondAng:n :n1 :n2]/DRC;
	[[a_modT cellAt:a_modsel :0] setFloatValue:d];
	if ([molobj bonded:n :n1] && [molobj bonded:n1 :n2]) 
		sprintf(s,"ang %d-%d-%d",n,n1,n2);
	else sprintf(s,"NB ang %d-%d-%d",n,n1,n2);
	[[a_modT2 cellAt:a_modsel :0] setStringValue:s];
	[[[[a_modS cellAt:a_modsel :0] setMinValue:d-20.0] setMaxValue:d+20.0] setFloatValue:d];
	break;
case 4:
	d=[molobj dihedral:n :n1 :n2 :n3]/DRC;
	[[a_modT cellAt:a_modsel :0] setFloatValue:d];
	if ([molobj bonded:n :n1]&&[molobj bonded:n1 :n2]&&[molobj bonded:n2 :n3]) 
		sprintf(s,"dihed %d-%d-%d-%d",n,n1,n2,n3);
	else sprintf(s,"NB dihed %d-%d-%d-%d",n,n1,n2,n3);
	[[a_modT2 cellAt:a_modsel :0] setStringValue:s];
	[[[[a_modS cellAt:a_modsel :0] setMinValue:-180.0] setMaxValue:180.0] setFloatValue:d];
	break;
default:
	[[a_modT cellAt:a_modsel :0] setStringValue:""];
	[[a_modT2 cellAt:a_modsel :0] setStringValue:""];
	break;	
}
return self;
}

- a_setModT:sender
{
int n,n1,n2,n3,ms;
float d,d2;

ms=[[sender selectedCell] tag];
d2=[sender floatValue]*DRC;
n=a_mod[ms].sel[0];
n1=a_mod[ms].sel[1];
n2=a_mod[ms].sel[2];
n3=a_mod[ms].sel[3];

switch (a_mod[ms].nsel) {
case 2:
	d=sqrt(SQR(mol[0].coord[n][0]-mol[0].coord[n1][0])+SQR(mol[0].coord[n][1]-mol[0].coord[n1][1])+SQR(mol[0].coord[n][2]-mol[0].coord[n1][2]));
	if ([molobj bonded:n :n1]&&d2>0.0) {
		[molobj modBondLen:(float)d2/DRC :(int)n :(int)n1];
		[molobj update:U_POS];
	}
	d=sqrt(SQR(mol[0].coord[n][0]-mol[0].coord[n1][0])+SQR(mol[0].coord[n][1]-mol[0].coord[n1][1])+SQR(mol[0].coord[n][2]-mol[0].coord[n1][2]));
	[[a_modS cellAt:a_modsel :0] setFloatValue:d];
	break;
case 3:
	d=[molobj bondAng:n :n1 :n2];
	if ([molobj bonded:n :n1] && [molobj bonded:n1 :n2] && d2!=0.0) {
		[molobj modBondAng:d2-d :n :n1 :n2];
		[molobj update:U_POS];
	}	
	d=[molobj bondAng:n :n1 :n2]/DRC;
	[[a_modS cellAt:ms :0] setFloatValue:d];
	break;
case 4:
	d=[molobj dihedral:n :n1 :n2 :n3];
	if ([molobj bonded:n :n1]&&[molobj bonded:n1 :n2]&&[molobj bonded:n2 :n3]) 
	{
		[molobj rotateAbout:d2-d :n :n1 :n2];
		[molobj update:U_POS];
	}
	d=[molobj dihedral:n :n1 :n2 :n3]/DRC;
	[[a_modS cellAt:ms :0] setFloatValue:d];
	break;
default:
	[[a_modT cellAt:ms :0] setStringValue:""];
	[[a_modT2 cellAt:ms :0] setStringValue:""];
	break;	
}
[self a_modRefr:ms];
return self;
}

- a_setModS:sender
{
int n,n1,n2,n3,ms;
float d,d2;

ms=[[sender selectedCell] tag];
d2=[sender floatValue]*DRC;
n=a_mod[ms].sel[0];
n1=a_mod[ms].sel[1];
n2=a_mod[ms].sel[2];
n3=a_mod[ms].sel[3];

switch (a_mod[ms].nsel) {
case 2:
	d=sqrt(SQR(mol[0].coord[n][0]-mol[0].coord[n1][0])+SQR(mol[0].coord[n][1]-mol[0].coord[n1][1])+SQR(mol[0].coord[n][2]-mol[0].coord[n1][2]));
	if ([molobj bonded:n :n1]&&d2>0.0) {
		[molobj modBondLen:(float)d2/DRC :(int)n :(int)n1];
		[molobj update:U_POS];
	}
	d=sqrt(SQR(mol[0].coord[n][0]-mol[0].coord[n1][0])+SQR(mol[0].coord[n][1]-mol[0].coord[n1][1])+SQR(mol[0].coord[n][2]-mol[0].coord[n1][2]));
	[[a_modT cellAt:a_modsel :0] setFloatValue:d];
	break;
case 3:
	d=[molobj bondAng:n :n1 :n2];
	if ([molobj bonded:n :n1] && [molobj bonded:n1 :n2]) {
		[molobj modBondAng:d2-d :n :n1 :n2];
		[molobj update:U_POS];
	}	
	d=[molobj bondAng:n :n1 :n2]/DRC;
	[[a_modT cellAt:ms :0] setFloatValue:d];
	break;
case 4:
	d=[molobj dihedral:n :n1 :n2 :n3];
	if ([molobj bonded:n :n1]&&[molobj bonded:n1 :n2]&&[molobj bonded:n2 :n3]) 
	{
		[molobj rotateAbout:d2-d :n :n1 :n2];
		[molobj update:U_POS];
	}
	d=[molobj dihedral:n :n1 :n2 :n3]/DRC;
	[[a_modT cellAt:ms :0] setFloatValue:d];
	break;
default:
	[[a_modT cellAt:ms :0] setStringValue:""];
	[[a_modT2 cellAt:ms :0] setStringValue:""];
	break;	
}
[self a_modRefr:ms];
return self;
}

/* refresh all mods EXCEPT nn */
- a_modRefr:(int)nn
{
int n,n1,n2,n3,i;
float d;

for (i=0; i<NMOD; i++) {
	if (i==nn) continue;
	n=a_mod[i].sel[0];
	n1=a_mod[i].sel[1];
	n2=a_mod[i].sel[2];
	n3=a_mod[i].sel[3];

	switch (a_mod[i].nsel) {
	case 2:
			d=sqrt(SQR(mol[0].coord[n][0]-mol[0].coord[n1][0])+SQR(mol[0].coord[n][1]-mol[0].coord[n1][1])+SQR(mol[0].coord[n][2]-mol[0].coord[n1][2]));
		[[a_modT cellAt:i :0] setFloatValue:d];
		[[a_modS cellAt:i :0] setFloatValue:d];
		break;
	case 3:
		d=[molobj bondAng:n :n1 :n2]/DRC;
		[[a_modT cellAt:i :0] setFloatValue:d];
		[[a_modS cellAt:i :0] setFloatValue:d];
		break;
	case 4:
		d=[molobj dihedral:n :n1 :n2 :n3]/DRC;
		[[a_modT cellAt:i :0] setFloatValue:d];
		[[a_modS cellAt:i :0] setFloatValue:d];
		break;
	}
}
return self;
}

- a_newPos:sender
{
int n;
if (nsel!=1) { [molobj error:"Select 1 atom." :NO]; return self;}
n=list[0].stab;

mol[0].coord[n][0]=[[a_pos1 cellAt:0 :0] floatValue];
mol[0].coord[n][1]=[[a_pos1 cellAt:1 :0] floatValue];
mol[0].coord[n][2]=[[a_pos1 cellAt:2 :0] floatValue];

[molobj update:U_POS];
return self;
}

- a_newLabel:sender
{
int n;

if (nsel!=1) { [molobj error:"Select 1 atom." :NO]; return self; }
n=list[0].stab;
mol[0].atom[n].lab=[sender intValue];
[molobj update:U_POS];
return self;
}

-a_labAll:sender
{
int i;

for (i=0; i<mol[0].numa; i++) mol[0].atom[i].lab=1;
[molobj update:U_POS];
return self;
}

-a_labNone:sender
{
int i;

for (i=0; i<mol[0].numa; i++) mol[0].atom[i].lab=0;
[molobj update:U_POS];
return self;
}

- a_newType:sender
{
int i,n,f=0;
char s[10];
if (nsel!=1) { [molobj error:"Select 1 atom first." :NO]; return self;}
n=list[0].stab;

mol[0].atom[n].charge=[[a_type cellAt:1 :0] floatValue];
if (fabs(mol[0].atom[n].charge)>.9) [molobj error:"Warning: large charge value." :NO];

strcpy(s,[[a_type cellAt:0 :0] stringValue]);
if (strlen(s)>3) { [molobj error:"Unknown atom type." :NO]; return self; }
for (i=0; i<strlen(s); i++) if (islower(s[i])) s[i]=toupper(s[i]);
if (strlen(s)==3||(islower(s[1])&&strlen(s)==2)) {
	mol[0].atom[n].type=s[2];
	for (i=0; i<NEL; i++) if (s[0]==elinfo[i].name[0]&&s[1]==elinfo[i].name[1]) break;
	if (i==NEL) { [molobj error:"Unknown atom type." :NO]; return self; }
	if (mol[0].atom[n].anum!=i) f=1;
	mol[0].atom[n].anum=i;
}
else {
	mol[0].atom[n].type=s[1];
	for (i=0; i<NEL; i++) if (s[0]==elinfo[i].name[0]&&elinfo[i].name[1]==' ') break;
	if (i==NEL||strlen(s)>3) { [molobj error:"Unknown atom type." :NO]; return self; }
	if (mol[0].atom[n].anum!=i) f=1;
	mol[0].atom[n].anum=i;
}
if (mol[0].atom[n].type<32) mol[0].atom[n].type=32;
if (f) {
	sprintf(list[n].text,"%3d  %c%c",n, elinfo[i].name[0],elinfo[i].name[1]);
	[a_select display];
}
[molobj update:U_POS];
return self;
}

- a_insp:sender
{
int i,j;
[self newInsp];
mode=0;
[inspectBox setContentView:atomIns];
if (nlist!=mol[0].numa) {
	if (list!=NULL) free(list);
	list=malloc(sizeof(struct SELDAT)*mol[0].numa);
	nlist=mol[0].numa;
}

for (i=0; i<nlist; i++) {
	j=mol[0].atom[i].anum;
	sprintf(list[i].text,"%3d  %c%c",i, elinfo[j].name[0],elinfo[j].name[1]);
}
nsel=0;

[a_select setData:nlist :list :self];
[a_select setHeader:" N  ATOM"];
[inspectBox display];
return self;
}

- t_insp:sender
{
int i;

[self newInsp];
mode=2;
[inspectBox setContentView:atabIns];
if (list!=NULL) free(list);
list=malloc(sizeof(struct SELDAT)*NEL);
nlist=NEL;

for (i=0; i<nlist; i++) {
	sprintf(list[i].text,"%-3d  %c%c",i+1, elinfo[i].name[0],elinfo[i].name[1]);
}

[t_select setData:nlist :list :self];
[t_select setHeader:"N   SYMB"];
[inspectBox display];
return self;
}

- newInsp
{
switch (mode) 
{
case 0:
	[a_select deselectAll];
	[self deselected:a_select :0 :0];
	break;
case 1:
	break;
case 2:
	[t_select deselectAll];
	[self deselected:t_select :0 :0];
	break;
}
return self;
}

- t_newSize:sender
{
int i;

size=[sender floatValue];
for (i=0; i<NEL; i++) elinfo[i].rad=size*elinfo[i].arad;
[molobj update:U_POS];
return self;
}

- t_newColor:sender
{
int i;
float c;

for (i=0; i<3; i++) {
	c=[[t_color cellAt:i :0] floatValue];
	if (c<0.0) [[t_color cellAt:i :0] setFloatValue:0.0];
	if (c>1.0) [[t_color cellAt:i :0] setFloatValue:1.0];
}

if (nsel!=1) return self;
for (i=0; i<3; i++) 
	elinfo[list[0].stab].color[i]=[[t_color cellAt:i :0] floatValue];
return self;
}

- t_newRad:sender
{
float f;
if (nsel!=1) return self;
f=[[t_radii cellAt:0 :0] floatValue];
if (f<.01) [[t_radii cellAt:0 :0] setFloatValue:.01];
if (f>4.0) [[t_radii cellAt:0 :0] setFloatValue:4.0];
elinfo[list[0].stab].arad=[[t_radii cellAt:0 :0] floatValue];
elinfo[list[0].stab].rad=elinfo[list[0].stab].arad*size;
return self;
}

- t_revert:sender
{
char *bpath;
char s[80],t[100];
int i;
FILE *in;

bpath=(char *)[[NXBundle mainBundle] directory];
sprintf(t,"%s/Library/MolViewer/MolViewer.dat",getenv("HOME"));
in=fopen(t,"r");
if (in==NULL) {
	sprintf(t,"%s/MolViewer.dat",bpath);
	in=fopen(t,"r");
	if (in==NULL) { printf("No .rad\n"); exit(0); }
}
for (i=0; fgets(s,79,in)!=NULL&&i<NEL; i++) {
	elinfo[i].color[0]=elinfo[i].color[1]=elinfo[i].color[2]=.7;
	elinfo[i].name[0]=s[0];
	if (s[1]!='\t') elinfo[i].name[1]=s[1];
	else elinfo[i].name[1]=' ';
	sscanf(&s[2],"%f %f %f %f",&elinfo[i].arad,&elinfo[i].color[0],&elinfo[i].
		color[1],&elinfo[i].color[2]);
	elinfo[i].rad=size*elinfo[i].arad;
}
fclose(in);

if (t[0]=='\n') t[0]=' ';
sprintf(s,"Reverted to %s",t);
[t_message setStringValue:s];
[molobj update:U_POS];
return self;
}

- t_save:sender
{
char s[80];
FILE *out;
int i;

sprintf(s,"%s/Library/MolViewer/MolViewer.dat",getenv("HOME"));
out=fopen(s,"w");
if (out==NULL) {
	[molobj error:"Can't write to $HOME/Library/MolViewer" :NO];
	return self;
}
for (i=0; i<NEL; i++) fprintf(out,"%c%c\t%5.3f\t%4.2f\t%4.2f\t%4.2f\n", 
	elinfo[i].name[0],elinfo[i].name[1],elinfo[i].arad,elinfo[i].color[0], 
	elinfo[i].color[1],elinfo[i].color[2]);
fclose(out);
strcat(s," written.");
[t_message setStringValue:s];
return self;
}

-t_update:sender
{
[molobj update:U_POS];
return self;
}

-t_makeQuick:sender
{
int i;

for (i=0; i<nsel; i++) {
	[d3View createQuick:list[i].stab];
}
[molobj error:"Rendering complete. Restart MolViewer to to make changes take effect." :NO];
return self;
}

- m_insp:sender
{
int i;
[self newInsp];
mode=1;
[inspectBox setContentView:aminoIns];
[molobj findAA:self];
if (nlist!=mol[0].numaa) {
	if (list!=NULL) free(list);
	list=malloc(sizeof(struct SELDAT)*mol[0].numaa);
	nlist=mol[0].numaa;
}

for (i=0; i<nlist; i++) {
	sprintf(list[i].text,"%3d  %s  %7.2f  %7.2f  %7.2f  %7.2f",i+1, acid[mol[0].am[i].anum].d2,mol[0].am[i].omega/DRC,mol[0].am[i].phi/DRC, mol[0].am[i].psi/DRC,mol[0].am[i].chi/DRC);
}
nsel=0;

[m_select setData:nlist :list :self];
[m_select setHeader:" N   AA    omega     phi      psi     chi"];
/*[m_select setGHeader:"                  w         f        y"]; */ 

[inspectBox display];
return self;
}

- m_upd:sender
{
int i;

for (i=0; i<nlist; i++) {
	sprintf(list[i].text,"%3d  %s  %7.2f  %7.2f  %7.2f  %7.2f",i+1, acid[mol[0].am[i].anum].d2,mol[0].am[i].omega/DRC,mol[0].am[i].phi/DRC, mol[0].am[i].psi/DRC,mol[0].am[i].chi/DRC);
}
nsel=0;

[inspectBox display];
return self;
}

-m_setAngS:sender
{
int n;
float a;

n=[sender selectedRow];
a=[[sender selectedCell] floatValue];
switch(n) {
case 0:
	[[m_angT cellAt:0 :0] setFloatValue:a];
	[molobj setOmega:a];
	break;
case 1:
	[[m_angT cellAt:1 :0] setFloatValue:a];
	[molobj setPhi:a];
	break;
case 2:
	[[m_angT cellAt:2 :0] setFloatValue:a];
	[molobj setPsi:a];
	break;
case 3: 
	[[m_angT cellAt:3 :0] setFloatValue:a];
	[molobj setChi:a];
	break;
}

return self;
}

-m_setAngT:sender
{
int n;
float a;

n=[sender selectedRow];
a=[[sender selectedCell] floatValue];
switch(n) {
case 0:
	[[m_angS cellAt:0 :0] setFloatValue:a];
	[molobj setOmega:a];
	break;
case 1:
	[[m_angS cellAt:1 :0] setFloatValue:a];
	[molobj setPhi:a];
	break;
case 2:
	[[m_angS cellAt:2 :0] setFloatValue:a];
	[molobj setPsi:a];
	break;
case 3:
	[[m_angS cellAt:3 :0] setFloatValue:a];
	[molobj setChi:a];
	break;
}

return self;
}

-m_xfer:sender
{
char s[MAXSEQ+1];
int i;

for (i=0; i<nlist; i++) {
	s[i]=acid[mol[0].am[i].anum].d1[0];
}
s[i]=0;
[m_amview setSeqStr:self :s];
return self;
}

- selected:sender :(int)n :(int)Nsel
{
int i,j;
char s[6];
nsel=Nsel;

switch (mode) {
case 0:
	[molobj setSelAtom:list];
	a_mod[a_modsel].nsel=nsel;
	for (i=0; i<4; i++) a_mod[a_modsel].sel[i]=list[i].stab;
	[self a_setupMod];
	if (nsel>1) {
		for (i=0; i<3; i++) [[a_pos1 cellAt:i :0] setStringValue:""];
		for (i=0; i<2; i++) [[a_pos2 cellAt:i :0] setStringValue:""];
		for (i=0; i<2; i++) [[a_type cellAt:i :0] setStringValue:""];
		for (i=0; i<4; i++) {
			if ((j=mol[0].atom[n].bnd[i])==-1) 
				[[a_bond cellAt:i :0] setStringValue:""];
			else [[a_bond cellAt:i :0] setIntValue:j];
		}
		[a_label setIntValue:0];
	} else {
		for (i=0; i<4; i++) {
			if ((j=mol[0].atom[n].bnd[i])==-1) 
				[[a_bond cellAt:i :0] setStringValue:""];
			else [[a_bond cellAt:i :0] setIntValue:j];
		}
		for (i=0; i<3; i++) [[a_pos1 cellAt:i :0] setFloatValue: 
			mol[0].coord[n][i]];
		[[a_type cellAt:1 :0] setFloatValue:mol[0].atom[n].charge];
		i=mol[0].atom[n].anum;
		s[0]=elinfo[i].name[0];
		s[1]=elinfo[i].name[1];
		if (s[1]==' ') { s[1]=mol[0].atom[n].type; s[2]=0; }
		else { s[2]=mol[0].atom[n].type; s[3]=0; }
		[[a_type cellAt:0 :0] setStringValue:s];
		[a_label setIntValue:mol[0].atom[n].lab];
	}
	break;
case 1:
	if (sender!=m_select) break;
	for (i=0; i<nlist; i++) mol[0].am[i].sel=list[i].sel;
	if (nsel==1) {
		[[m_angS cellAt:0 :0] setFloatValue:mol[0].am[list[0].stab].omega/DRC];
		[[m_angS cellAt:1 :0] setFloatValue:mol[0].am[list[0].stab].phi/DRC];
		[[m_angS cellAt:2 :0] setFloatValue:mol[0].am[list[0].stab].psi/DRC];
		[[m_angS cellAt:3 :0] setFloatValue:mol[0].am[list[0].stab].chi/DRC];
		[[m_angT cellAt:0 :0] setFloatValue:mol[0].am[list[0].stab].omega/DRC];
		[[m_angT cellAt:1 :0] setFloatValue:mol[0].am[list[0].stab].phi/DRC];
		[[m_angT cellAt:2 :0] setFloatValue:mol[0].am[list[0].stab].psi/DRC];
		[[m_angT cellAt:3 :0] setFloatValue:mol[0].am[list[0].stab].chi/DRC];
	}
	break;
case 2:	
	if (sender!=t_select) break;
	if (nsel>1) {
		for (i=0; i<3; i++) [[t_color cellAt:i :0] setStringValue:""];
		for (i=0; i<2; i++) [[t_radii cellAt:i :0] setStringValue:""];
	}
	else {
		for (i=0; i<3; i++) [[t_color cellAt:i :0] setFloatValue:elinfo[n].color[i]];
		[[t_radii cellAt:0 :0] setFloatValue:elinfo[n].arad];
/*		[[t_radii cellAt:1 :0] setFloatValue:];*/
	}
	break;		
}
return self;
} 


- deselected:sender :(int)n :(int)Nsel
{
int i;
nsel=Nsel;
switch (mode) {
case 0:
	a_mod[a_modsel].nsel=nsel;
	for (i=0; i<4; i++) a_mod[a_modsel].sel[i]=list[i].stab;
	[self a_setupMod];

	for (i=0; i<4; i++) [[a_bond cellAt:i :0] setStringValue:""];
	for (i=0; i<3; i++) [[a_pos1 cellAt:i :0] setStringValue:""];
	for (i=0; i<2; i++) [[a_pos2 cellAt:i :0] setStringValue:""];
	for (i=0; i<2; i++) [[a_type cellAt:i :0] setStringValue:""];
	[a_label setIntValue:0];
	[molobj setSelAtom:list];
	break;
case 1:
	if (sender!=m_select) break;
	for (i=0; i<nlist; i++) mol[0].am[i].sel=list[i].sel;
	break;	
case 2:
	if (sender!=t_select) break;
	for (i=0; i<3; i++) [[t_color cellAt:i :0] setStringValue:""];
	for (i=0; i<2; i++) [[t_radii cellAt:i :0] setStringValue:""];
	break;
}
return self;
}
@end

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.