source: trunk/gui/vizservers/pymol/layer1/P.c @ 700

Last change on this file since 700 was 700, checked in by nkissebe, 17 years ago

initial modifications to pyMol for remote visualization server support

File size: 64.0 KB
Line 
1/*
2A* -------------------------------------------------------------------
3B* This file contains source code for the PyMOL computer program
4C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
5D* -------------------------------------------------------------------
6E* It is unlawful to modify or remove this copyright notice.
7F* -------------------------------------------------------------------
8G* Please see the accompanying LICENSE file for further information.
9H* -------------------------------------------------------------------
10I* Additional authors of this source file include:
11-*
12-*
13-*
14Z* -------------------------------------------------------------------
15*/
16
17/* meaning of defines
18
19_PYMOL_MONOLITHIC: means that we're building PyMOL and its Python C
20dependencies as one C library.  That means we need to explicitly call
21the initialization functions for these libraries on startup.
22
23*/
24
25#ifndef _PYMOL_NOPY
26
27#include"os_predef.h"
28#include"Base.h"
29
30#define MAX_SAVED_THREAD ((PYMOL_MAX_THREADS)+3)
31
32
33/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
34#ifdef WIN32
35#include<windows.h>
36#include<process.h>
37#include<winappc.h>
38#endif
39/* END PROPRIETARY CODE SEGMENT */
40
41#include"os_python.h"
42
43#include"os_std.h"
44#include"os_time.h"
45#include"os_unix.h"
46
47#include"MemoryDebug.h"
48#include"Base.h"
49#include"Err.h"
50#include"P.h"
51#include"PConv.h"
52#include"Ortho.h"
53#include"Cmd.h"
54#include"main.h"
55#include"AtomInfo.h"
56#include"CoordSet.h"
57#include"Util.h"
58#include"Executive.h"
59#include"PyMOLOptions.h"
60#include"PyMOL.h"
61
62
63
64/* all of the following Python objects must be invariant & global for the application */
65
66/* local to this C code module */
67
68static PyObject *P_pymol = NULL;
69static PyObject *P_pymol_dict = NULL; /* must be refomed into globals and instance properties */
70static PyObject *P_cmd = NULL;
71
72/* used elsewhere */
73
74PyObject *P_menu = NULL; /* menu definitions are currently global */
75PyObject *P_xray = NULL; /* okay as global */
76PyObject *P_chempy = NULL; /* okay as global */
77PyObject *P_models = NULL; /* okay as global */
78PyObject *P_setting = NULL; /* must be reformed somehow */
79PyObject *P_embed = NULL;
80
81/* local to this module */
82
83static PyObject *P_povray = NULL;
84static PyObject *P_traceback = NULL;
85static PyObject *P_parser = NULL;
86
87static PyObject *P_lock = NULL; /* API locks */
88static PyObject *P_lock_attempt = NULL;
89static PyObject *P_unlock = NULL;
90
91static PyObject *P_lock_c = NULL; /* C locks */
92static PyObject *P_unlock_c = NULL;
93
94static PyObject *P_lock_status = NULL; /* status locks */
95static PyObject *P_lock_status_attempt = NULL; /* status locks */
96static PyObject *P_unlock_status = NULL;
97
98static PyObject *P_lock_glut = NULL; /* GLUT locks */
99static PyObject *P_unlock_glut = NULL;
100
101/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
102#ifdef WIN32
103static PyObject *P_time = NULL;
104static PyObject *P_sleep = NULL;
105#endif
106/* END PROPRIETARY CODE SEGMENT */
107
108static PyObject *P_main = NULL;
109static PyObject *P_vfont = NULL;
110
111#define P_log_file_str "_log_file"
112
113#define xxxPYMOL_NEW_THREADS
114
115unsigned int PyThread_get_thread_ident(void); /* critical functionality */
116
117typedef struct {
118  int id;
119  PyThreadState *state;
120} SavedThreadRec;
121
122void PRunStringModule(PyMOLGlobals *G,char *str);
123
124void PLockStatus(void) /* assumes we have the GIL */
125{
126  PXDecRef(PyObject_CallFunction(P_lock_status,NULL));
127}
128
129int PLockStatusAttempt(void) /* assumes we have the GIL */
130{
131  int result = true;
132  PyObject *got_lock = PyObject_CallFunction(P_lock_status_attempt,NULL);
133  if(got_lock) {
134    if(!PyInt_AsLong(got_lock)) {
135      result = false;
136    }
137    Py_DECREF(got_lock);
138  }
139  return result;
140}
141void PUnlockStatus(void) /* assumes we have the GIL */
142{
143  PXDecRef(PyObject_CallFunction(P_unlock_status,NULL));
144}
145
146static void PLockGLUT(void) /* assumes we have the GIL */
147{
148  PXDecRef(PyObject_CallFunction(P_lock_glut,NULL));
149}
150
151static void PUnlockGLUT(void) /* assumes we have the GIL */
152{
153  PXDecRef(PyObject_CallFunction(P_unlock_glut,NULL));
154}
155
156static SavedThreadRec SavedThread[MAX_SAVED_THREAD];
157
158int P_glut_thread_keep_out = 0;
159unsigned int P_glut_thread_id;
160
161/* enables us to keep glut out if by chance it grabs the API
162 * in the middle of a nested API based operation */
163
164void PCatchInit(void);
165void my_interrupt(int a);
166char *getprogramname(void);
167
168/*
169PyObject *GetBondsDict(PyMOLGlobals *G)
170{
171  PyObject *result = NULL;
172  result = PyObject_GetAttrString(P_chempy,"bonds");
173  if(!result) ErrMessage(G,"PyMOL","can't find 'chempy.bonds.bonds'");
174  return(result);
175}
176*/
177
178PyObject *PGetFontDict(PyMOLGlobals *G, float size,int face,int style)
179{ /* assumes we have a valid interpreter lock */
180  PyObject *result = NULL;
181
182  if(!P_vfont) {
183    PRunStringModule(G,"import vfont\n"); 
184    P_vfont = PyDict_GetItemString(P_pymol_dict,"vfont");
185  }
186  if(!P_vfont) {
187    PRINTFB(G,FB_Python,FB_Errors)
188      " PyMOL-Error: can't find module 'vfont'"
189      ENDFB(G);
190  }
191  else {
192    result = PyObject_CallMethod(P_vfont,"get_font","fii",size,face,style);
193  }
194  return(PConvAutoNone(result));
195}
196
197int PComplete(PyMOLGlobals *G,char *str,int buf_size)
198{
199  int ret = false;
200  PyObject *result;
201  char *st2;
202  PBlockAndUnlockAPI(G);
203  if(G->P_inst->complete) {
204    result = PyObject_CallFunction(G->P_inst->complete,"s",str);
205    if(result) {
206      if(PyString_Check(result)) {
207        st2 = PyString_AsString(result);
208        UtilNCopy(str,st2,buf_size);
209        ret=true;
210      }
211      Py_DECREF(result);
212    }
213  }
214  PLockAPIAndUnblock(G);
215  return(ret);
216}
217
218int PTruthCallStr0(PyObject *object,char *method)
219{
220  int result = false;
221  PyObject *tmp;
222  tmp = PyObject_CallMethod(object,method,"");
223  if(tmp) {
224    if(PyObject_IsTrue(tmp))
225      result = 1;
226    Py_DECREF(tmp);
227  }
228  return(result);
229}
230
231
232int PTruthCallStr(PyObject *object,char *method,char *argument)
233{
234  int result = false;
235  PyObject *tmp;
236  tmp = PyObject_CallMethod(object,method,"s",argument);
237  if(tmp) {
238    if(PyObject_IsTrue(tmp))
239      result = 1;
240    Py_DECREF(tmp);
241  }
242  return(result);
243}
244
245int PTruthCallStr1i(PyObject *object,char *method,int argument)
246{
247  int result = false;
248  PyObject *tmp;
249  tmp = PyObject_CallMethod(object,method,"i",argument);
250  if(tmp) {
251    if(PyObject_IsTrue(tmp))
252      result = 1;
253    Py_DECREF(tmp);
254  }
255  return(result);
256}
257int PTruthCallStr4i(PyObject *object,char *method,int a1,int a2,int a3,int a4)
258{
259  int result = false;
260  PyObject *tmp;
261  tmp = PyObject_CallMethod(object,method,"iiii",a1,a2,a3,a4);
262  if(tmp) {
263    if(PyObject_IsTrue(tmp))
264      result = 1;
265    Py_DECREF(tmp);
266  }
267  return(result);
268}
269                                       
270void PXDecRef(PyObject *obj)
271{
272  Py_XDECREF(obj);
273}
274
275void PSleepWhileBusy(PyMOLGlobals *G,int usec)
276{
277#ifndef WIN32
278  struct timeval tv;
279  PRINTFD(G,FB_Threads)
280    " PSleep-DEBUG: napping.\n"
281  ENDFD;
282  tv.tv_sec=0;
283  tv.tv_usec=usec;
284  select(0,NULL,NULL,NULL,&tv);
285  PRINTFD(G,FB_Threads)
286    " PSleep-DEBUG: nap over.\n"
287  ENDFD;
288#else
289/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
290  PBlock(G);
291  PXDecRef(PyObject_CallFunction(P_sleep,"f",usec/1000000.0));
292  PUnblock(G);
293/* END PROPRIETARY CODE SEGMENT */
294#endif
295}
296
297void PSleepUnlocked(PyMOLGlobals *G,int usec)
298{ /* can only be called by the glut process */
299#ifndef WIN32
300  fd_set fds; /* Sleep Interruption Patch *NJK* */
301  struct timeval tv;
302  PRINTFD(G,FB_Threads)
303    " PSleep-DEBUG: napping.\n"
304  ENDFD;
305  tv.tv_sec=0;
306  tv.tv_usec=usec;
307  /* Sleep Interruption Patch *NJK* */
308  FD_ZERO(&fds);
309  FD_SET(TempPyMOLGlobals->CmdPipe[0],&fds);
310  select(TempPyMOLGlobals->CmdPipe[0]+1,&fds,NULL,NULL,&tv);
311  if (FD_ISSET(TempPyMOLGlobals->CmdPipe[0],&fds)) {
312    char c;
313    read(TempPyMOLGlobals->CmdPipe[0],&c,1);
314  }
315  PRINTFD(G,FB_Threads)
316    " PSleep-DEBUG: nap over.\n"
317  ENDFD;
318#else
319/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
320  PBlock(G);
321  PXDecRef(PyObject_CallFunction(P_sleep,"f",usec/1000000.0));
322  PUnblock(G);
323/* END PROPRIETARY CODE SEGMENT */
324#endif
325}
326
327void PSleep(PyMOLGlobals *G,int usec)
328{ /* can only be called by the glut process */
329#ifndef WIN32
330  struct timeval tv;
331  PUnlockAPIAsGlut(G);
332  PRINTFD(G,FB_Threads)
333    " PSleep-DEBUG: napping.\n"
334  ENDFD;
335  tv.tv_sec=0;
336  tv.tv_usec=usec;
337  select(0,NULL,NULL,NULL,&tv);
338  PRINTFD(G,FB_Threads)
339    " PSleep-DEBUG: nap over.\n"
340  ENDFD;
341  PLockAPIAsGlut(G,true);
342#else
343/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
344  PBlockAndUnlockAPI(G);
345  PXDecRef(PyObject_CallFunction(P_sleep,"f",usec/1000000.0));
346  PLockAPIAndUnblock(G);
347/* END PROPRIETARY CODE SEGMENT */
348#endif
349
350}
351
352static PyObject *PCatchWrite(PyObject *self,    PyObject *args);
353
354void my_interrupt(int a)
355{
356  exit(EXIT_FAILURE);
357}
358
359void PDumpTraceback(PyObject *err)
360{
361  PyObject_CallMethod(P_traceback,"print_tb","O",err);
362}
363
364void PDumpException()
365{
366  PyObject_CallMethod(P_traceback,"print_exc","");
367}
368
369int PAlterAtomState(PyMOLGlobals *G,float *v,char *expr,int read_only,
370                    AtomInfoType *at,char *model,int index,
371                    PyObject *space)
372     /* assumes Blocked python interpreter*/
373{
374  PyObject *dict;
375  int result=true;
376  float f[3];
377  PyObject *x_id1,*x_id2=NULL,*y_id1,*y_id2=NULL,*z_id1,*z_id2=NULL;
378  char atype[7];
379  PyObject *flags_id1=NULL,*flags_id2=NULL;
380  int flags;
381  dict = PyDict_New();
382 
383  if(at) {
384    if(at->hetatm)
385      strcpy(atype,"HETATM");
386    else
387      strcpy(atype,"ATOM");
388
389    /* immutables */
390    PConvStringToPyDictItem(dict,"model",model);
391    PConvIntToPyDictItem(dict,"index",index+1);
392   
393    PConvStringToPyDictItem(dict,"type",atype);
394    PConvStringToPyDictItem(dict,"name",at->name);
395    PConvStringToPyDictItem(dict,"resn",at->resn);
396    PConvStringToPyDictItem(dict,"resi",at->resi);
397    PConvIntToPyDictItem(dict,"resv",at->resv); /* subordinate to resi */
398    PConvStringToPyDictItem(dict,"chain",at->chain);
399    PConvStringToPyDictItem(dict,"alt",at->alt);
400    PConvStringToPyDictItem(dict,"segi",at->segi);
401    PConvStringToPyDictItem(dict,"elem",at->elem);
402    PConvStringToPyDictItem(dict,"ss",at->ssType);
403
404    {
405      char null_st[1] = "";
406      char *st = null_st;
407     
408      if(at->textType) st = OVLexicon_FetchCString(G->Lexicon,at->textType);
409      PConvStringToPyDictItem(dict,"text_type",st);
410     
411      st = null_st;
412      if(at->label) st = OVLexicon_FetchCString(G->Lexicon,at->label);
413      PConvStringToPyDictItem(dict,"label",st);
414    }
415    PConvIntToPyDictItem(dict,"numeric_type",at->customType);
416    PConvFloatToPyDictItem(dict,"q",at->q);
417    PConvFloatToPyDictItem(dict,"b",at->b);
418    PConvFloatToPyDictItem(dict,"vdw",at->vdw);
419    PConvFloatToPyDictItem(dict,"elec_radius",at->elec_radius);
420    PConvFloatToPyDictItem(dict,"partial_charge",at->partialCharge);
421    PConvIntToPyDictItem(dict,"formal_charge",at->formalCharge);
422    PConvIntToPyDictItem(dict,"cartoon",at->cartoon);
423    PConvIntToPyDictItem(dict,"color",at->color);
424    PConvIntToPyDictItem(dict,"ID",at->id);
425    PConvIntToPyDictItem(dict,"rank",at->rank);
426
427    /* mutables */
428    flags_id1 = PConvIntToPyDictItem(dict,"flags",at->flags);
429  }
430  x_id1 = PConvFloatToPyDictItem(dict,"x",v[0]);
431  y_id1 = PConvFloatToPyDictItem(dict,"y",v[1]);
432  z_id1 = PConvFloatToPyDictItem(dict,"z",v[2]);
433  PXDecRef(PyRun_String(expr,Py_single_input,space,dict));
434  if(PyErr_Occurred()) {
435    PyErr_Print();
436    result=false;
437  } else if(!read_only) {
438    if(result) {
439      if(!(x_id2 = PyDict_GetItemString(dict,"x")))
440        result=false;
441      else if(!(y_id2 = PyDict_GetItemString(dict,"y")))
442        result=false;
443      else if(!(z_id2 = PyDict_GetItemString(dict,"z")))
444        result=false;
445      else if(at) {
446        if(!(flags_id2 = PyDict_GetItemString(dict,"flags")))
447          result=false;
448      }
449      if(PyErr_Occurred()) {
450        PyErr_Print();
451        result=false;
452        ErrMessage(G,"AlterState","Aborting on error. Assignment may be incomplete.");
453      }
454    }
455    if(result) {
456      f[0]=(float)PyFloat_AsDouble(x_id2);
457      f[1]=(float)PyFloat_AsDouble(y_id2);
458      f[2]=(float)PyFloat_AsDouble(z_id2);
459      if(at)
460        if(flags_id1!=flags_id2) {
461          if(!PConvPyObjectToInt(flags_id2,&flags))
462            result=false;
463          else
464            at->flags = flags;
465        }
466      if(PyErr_Occurred()) {
467        PyErr_Print();
468        result=false;
469        ErrMessage(G,"AlterState","Aborting on error. Assignment may be incomplete.");
470      } else {
471        v[0]=f[0];
472        v[1]=f[1];
473        v[2]=f[2];
474      }
475    }
476   
477  }
478  Py_DECREF(dict);
479  return result;
480}
481
482int PAlterAtom(PyMOLGlobals *G,
483               AtomInfoType *at,char *expr,int read_only,
484               char *model,int index,PyObject *space)
485{
486  /* assumes Blocked python interpreter*/
487  WordType buf;
488  AtomName name;
489  PyObject *name_id1,*name_id2=NULL;
490  AtomName elem;
491  PyObject *elem_id1,*elem_id2=NULL;
492  ResName resn;
493  PyObject *resn_id1,*resn_id2=NULL;
494  ResIdent resi;
495  PyObject *resi_id1,*resi_id2=NULL;
496  int resv;
497  PyObject *resv_id1,*resv_id2=NULL;
498  Chain chain;
499  PyObject *chain_id1,*chain_id2=NULL;
500  Chain alt;
501  PyObject *alt_id1,*alt_id2=NULL;
502  SegIdent segi;
503  PyObject *flags_id1,*flags_id2=NULL;
504  int flags;
505  PyObject *segi_id1,*segi_id2=NULL;
506  PyObject *text_type_id1,*text_type_id2=NULL;
507  SSType ssType;
508  PyObject *ss_id1,*ss_id2=NULL;
509  char atype[7];
510  PyObject *type_id1,*type_id2=NULL;
511  float b,q,partialCharge,vdw,elec_radius;
512  PyObject *b_id1,*b_id2=NULL;
513  PyObject *q_id1,*q_id2=NULL;
514  PyObject *partial_charge_id1,*partial_charge_id2=NULL;
515  PyObject *vdw_id1,*vdw_id2=NULL;
516  PyObject *elec_radius_id1,*elec_radius_id2=NULL;
517  int formalCharge,numericType;
518  PyObject *formal_charge_id1,*formal_charge_id2=NULL;
519  PyObject *numeric_type_id1,*numeric_type_id2=NULL;
520  int cartoon;
521  PyObject *cartoon_id1,*cartoon_id2=NULL;
522  int color;
523  PyObject *color_id1,*color_id2=NULL;
524  PyObject *label_id1,*label_id2=NULL;
525  int id;
526  PyObject *ID_id1,*ID_id2=NULL;
527  int rank;
528  PyObject *rank_id1,*rank_id2=NULL;
529  PyObject *state_id1,*state_id2=NULL;
530  int state;
531  PyObject *dict;
532  int result=true;
533 
534  if(at->hetatm)
535    strcpy(atype,"HETATM");
536  else
537    strcpy(atype,"ATOM");
538
539  /* PBlockAndUnlockAPI() is not safe, thus these
540   * expressions must not call the PyMOL API...
541   * what if "at" is destroyed by another thread? */
542
543  dict = PyDict_New();
544
545  /* immutables */
546  PConvStringToPyDictItem(dict,"model",model);
547  PConvIntToPyDictItem(dict,"index",index+1);
548
549  /* mutables */
550  type_id1 = PConvStringToPyDictItem(dict,"type",atype);
551  name_id1 = PConvStringToPyDictItem(dict,"name",at->name);
552  resn_id1 = PConvStringToPyDictItem(dict,"resn",at->resn);
553  flags_id1 = PConvIntToPyDictItem(dict,"flags",at->flags);
554  resi_id1 = PConvStringToPyDictItem(dict,"resi",at->resi);
555  resv_id1 = PConvIntToPyDictItem(dict,"resv",at->resv); /* subordinate to resi */
556  chain_id1 = PConvStringToPyDictItem(dict,"chain",at->chain);
557  alt_id1 = PConvStringToPyDictItem(dict,"alt",at->alt);
558  segi_id1 = PConvStringToPyDictItem(dict,"segi",at->segi);
559  elem_id1 = PConvStringToPyDictItem(dict,"elem",at->elem);
560  ss_id1 = PConvStringToPyDictItem(dict,"ss",at->ssType);
561  numeric_type_id1 = PConvIntToPyDictItem(dict,"numeric_type",at->customType);
562  q_id1 = PConvFloatToPyDictItem(dict,"q",at->q);
563  b_id1 = PConvFloatToPyDictItem(dict,"b",at->b);
564  vdw_id1 = PConvFloatToPyDictItem(dict,"vdw",at->vdw);
565  elec_radius_id1 = PConvFloatToPyDictItem(dict,"elec_radius",at->elec_radius);
566  partial_charge_id1 = PConvFloatToPyDictItem(dict,"partial_charge",at->partialCharge);
567  formal_charge_id1 = PConvIntToPyDictItem(dict,"formal_charge",at->formalCharge);
568  cartoon_id1 = PConvIntToPyDictItem(dict,"cartoon",at->cartoon);
569
570  {
571    char null_st[1] = "";
572    char *st = null_st;
573
574    if(at->textType) st = OVLexicon_FetchCString(G->Lexicon,at->textType);
575    text_type_id1 = PConvStringToPyDictItem(dict,"text_type",st);
576
577    st = null_st;
578    if(at->label) st = OVLexicon_FetchCString(G->Lexicon,at->label);
579    label_id1 = PConvStringToPyDictItem(dict,"label",st);
580  }
581
582  color_id1 = PConvIntToPyDictItem(dict,"color",at->color);
583  ID_id1 = PConvIntToPyDictItem(dict,"ID",at->id);
584  state_id1 = PConvIntToPyDictItem(dict,"state",at->discrete_state);
585  rank_id1 = PConvIntToPyDictItem(dict,"rank",at->rank);
586
587  PXDecRef(PyRun_String(expr,Py_single_input,space,dict));
588  if(PyErr_Occurred()) {
589    ErrMessage(G,"Alter","Aborting on error. Assignment may be incomplete.");
590    PyErr_Print();
591    result=false;
592  } else if(read_only) {
593    result=true;
594  } if(PyErr_Occurred()) {
595    PyErr_Print();
596    result=false;
597  } else if(!read_only) {
598
599    if(result) {
600      /* get new object IDs */
601     
602      if(!(type_id2 = PyDict_GetItemString(dict,"type")))
603        result=false;
604      else if(!(name_id2 = PyDict_GetItemString(dict,"name")))
605        result=false;
606      else if(!(elem_id2 = PyDict_GetItemString(dict,"elem")))
607        result=false;
608      else if(!(resn_id2 = PyDict_GetItemString(dict,"resn")))
609        result=false;
610      else if(!(flags_id2 = PyDict_GetItemString(dict,"flags")))
611        result=false;
612      else if(!(resi_id2 = PyDict_GetItemString(dict,"resi")))
613        result=false;
614      else if(!(resv_id2 = PyDict_GetItemString(dict,"resv")))
615        result=false;
616      else if(!(segi_id2 = PyDict_GetItemString(dict,"segi")))
617        result=false;
618      else if(!(alt_id2 = PyDict_GetItemString(dict,"alt")))
619        result=false;
620      else if(!(chain_id2 = PyDict_GetItemString(dict,"chain")))
621        result=false;
622      else if(!(text_type_id2 = PyDict_GetItemString(dict,"text_type")))
623        result=false;
624      else if(!(ss_id2 = PyDict_GetItemString(dict,"ss")))
625        result=false;
626      else if(!(b_id2 = PyDict_GetItemString(dict,"b")))
627        result=false;
628      else if(!(q_id2 = PyDict_GetItemString(dict,"q")))
629        result=false;
630      else if(!(vdw_id2=PyDict_GetItemString(dict,"vdw")))
631        result=false;
632      else if(!(elec_radius_id2=PyDict_GetItemString(dict,"elec_radius")))
633        result=false;
634      else if(!(partial_charge_id2 = PyDict_GetItemString(dict,"partial_charge")))
635        result=false;
636      else if(!(formal_charge_id2 = PyDict_GetItemString(dict,"formal_charge")))
637        result=false;
638      else if(!(cartoon_id2 = PyDict_GetItemString(dict,"cartoon")))
639        result=false;
640      else if(!(color_id2=PyDict_GetItemString(dict,"color")))
641        result=false;
642      else if(!(label_id2=PyDict_GetItemString(dict,"label")))
643        result=false;
644      if(!(numeric_type_id2 = PyDict_GetItemString(dict,"numeric_type")))
645        result=false;
646      if(!(ID_id2 = PyDict_GetItemString(dict,"ID")))
647        result=false;
648      if(!(state_id2 = PyDict_GetItemString(dict,"state")))
649        result=false;
650      if(!(rank_id2 = PyDict_GetItemString(dict,"rank")))
651        result=false;
652
653      if(PyErr_Occurred()) {
654        PyErr_Print();
655        result=false;
656      }
657    }
658    if(result) {
659      if(type_id1!=type_id2) {
660        if(!PConvPyObjectToStrMaxLen(type_id2,atype,6))
661          result=false;
662        else
663          at->hetatm=((atype[0]=='h')||(atype[0]=='H'));
664      }
665      if(name_id1!=name_id2) {
666        if(!PConvPyObjectToStrMaxLen(name_id2,name,sizeof(AtomName)-1))
667          result=false;
668        else
669          strcpy(at->name,name);
670      }
671      if(elem_id1!=elem_id2) {
672        if(!PConvPyObjectToStrMaxLen(elem_id2,elem,sizeof(AtomName)-1))
673          result=false;
674        else {
675          strcpy(at->elem,elem);
676          AtomInfoAssignParameters(G,at);
677        }
678      }
679      if(resn_id1!=resn_id2) {
680        if(!PConvPyObjectToStrMaxLen(resn_id2,resn,sizeof(ResName)-1))
681          result=false;
682        else
683          strcpy(at->resn,resn);
684      }
685      if(resi_id1!=resi_id2) {
686        if(!PConvPyObjectToStrMaxLen(resi_id2,resi,sizeof(ResIdent)-1))
687          result=false;
688        else {
689          if(strcmp(at->resi,resi)!=0)
690            at->resv=AtomResvFromResi(resi);
691          strcpy(at->resi,resi);
692        }
693      } else if (resv_id1!=resv_id2) {
694        if(!PConvPyObjectToInt(resv_id2,&resv))
695          result=false;
696        else {
697          sprintf(buf,"%d",resv);
698          buf[sizeof(ResIdent)-1]=0;
699          strcpy(at->resi,buf);
700        }
701       
702      }
703      if(segi_id1!=segi_id2) {
704        if(!PConvPyObjectToStrMaxLen(segi_id2,segi,sizeof(SegIdent)-1))
705          result=false;
706        else
707          strcpy(at->segi,segi);
708
709      }
710      if(chain_id1!=chain_id2) {
711        if(!PConvPyObjectToStrMaxLen(chain_id2,chain,sizeof(Chain)-1))
712          result=false;
713        else
714          strcpy(at->chain,chain);
715      }
716      if(alt_id1!=alt_id2) {
717        if(!PConvPyObjectToStrMaxLen(alt_id2,alt,sizeof(Chain)-1))
718          result=false;
719        else
720          strcpy(at->alt,alt);
721      }
722      if(text_type_id1!=text_type_id2) {
723       
724        OrthoLineType temp;
725        if(at->textType) {
726          OVLexicon_DecRef(G->Lexicon,at->textType);
727        }
728        at->textType = 0;
729
730        if(PConvPyObjectToStrMaxLen(text_type_id2,temp,sizeof(OrthoLineType)-1)) {
731          if(temp[0]) {
732            OVreturn_word result = OVLexicon_GetFromCString(G->Lexicon,temp);
733            if(OVreturn_IS_OK(result)) {
734              at->textType = result.word;
735            }
736          }
737        }
738      }
739      if(ss_id1!=ss_id2) {
740        if(!PConvPyObjectToStrMaxLen(ss_id2,ssType,sizeof(SSType)-1))
741          result=false;
742        else {
743          strcpy(at->ssType,ssType);
744          at->ssType[0] = toupper(at->ssType[0]);
745        }
746      }
747      if(b_id1!=b_id2) {
748        if(!PConvPyObjectToFloat(b_id2,&b))
749          result=false;
750        else
751          at->b=b;
752      }
753      if(q_id1!=q_id2) {
754        if(!PConvPyObjectToFloat(q_id2,&q))
755          result=false;
756        else
757          at->q=q;
758      }
759      if(vdw_id1!=vdw_id2) {
760        if(!PConvPyObjectToFloat(vdw_id2,&vdw))
761          result=false;
762        else
763          at->vdw=vdw;
764
765      }
766      if(elec_radius_id1!=elec_radius_id2) {
767        if(!PConvPyObjectToFloat(elec_radius_id2,&elec_radius))
768          result=false;
769        else
770          at->elec_radius=elec_radius;
771      }
772      if(partial_charge_id1!=partial_charge_id2) {
773        if(!PConvPyObjectToFloat(partial_charge_id2,&partialCharge))
774          result=false;
775        else
776          at->partialCharge=partialCharge;
777
778      }
779      if(formal_charge_id1!=formal_charge_id2) {
780        if(!PConvPyObjectToInt(formal_charge_id2,&formalCharge))
781          result=false;
782        else {
783          at->formalCharge=formalCharge;
784          at->chemFlag = false; /* invalidate chemistry info for this atom */
785        }
786
787      }
788      if(cartoon_id1!=cartoon_id2) {
789        if(!PConvPyObjectToInt(cartoon_id2,&cartoon))
790          result=false;
791        else
792          at->cartoon=cartoon;
793      }
794      if(color_id1!=color_id2) {
795        if(!PConvPyObjectToInt(color_id2,&color))
796          result=false;
797        else
798          at->color=color;
799      }
800      if(state_id1!=state_id2) {
801        if(!PConvPyObjectToInt(state_id2,&state))
802          result=false;
803        else
804          at->discrete_state=state;
805      }
806      if(label_id1!=label_id2) {
807        OrthoLineType temp;
808        if(at->label) {
809          OVLexicon_DecRef(G->Lexicon,at->label);
810        }
811        at->label = 0;
812
813        if(PConvPyObjectToStrMaxLen(label_id2,temp,sizeof(OrthoLineType)-1)) {
814          if(temp[0]) {
815            OVreturn_word result = OVLexicon_GetFromCString(G->Lexicon,temp);
816            if(OVreturn_IS_OK(result)) {
817              at->label = result.word;
818            }
819          }
820        }
821      }
822      if(flags_id1!=flags_id2) {
823        if(!PConvPyObjectToInt(flags_id2,&flags))
824          result=false;
825        else
826          at->flags = flags;
827      }
828
829      if(numeric_type_id1!=numeric_type_id2) {
830        if(!PConvPyObjectToInt(numeric_type_id2,&numericType))
831          result=false;
832        else
833          at->customType = numericType;
834      }
835      if(ID_id1!=ID_id2) {
836        if(!PConvPyObjectToInt(ID_id2,&id))
837          result=false;
838        else
839          at->id=id;
840      }
841      if(rank_id1!=rank_id2) {
842        if(!PConvPyObjectToInt(rank_id2,&rank))
843          result=false;
844        else
845          at->rank=rank;
846      }
847
848      if(PyErr_Occurred()) {
849        PyErr_Print();
850        result=false;
851      }
852    }
853    if(!result) {
854      ErrMessage(G,"Alter","Aborting on error. Assignment may be incomplete.");
855    }
856  }
857  Py_DECREF(dict);
858  return(result);
859}
860
861int PLabelAtom(PyMOLGlobals *G, AtomInfoType *at,char *model,char *expr,int index)
862{
863  PyObject *dict;
864  PyObject *P_inst_dict = G->P_inst->dict;
865  int result;
866  OrthoLineType label;
867  char atype[7];
868  OrthoLineType buffer;
869  if(at->hetatm)
870    strcpy(atype,"HETATM");
871  else
872    strcpy(atype,"ATOM");
873  PBlock(G);
874  /* PBlockAndUnlockAPI() is not safe.
875   * what if "at" is destroyed by another thread? */
876  dict = PyDict_New();
877
878  PConvStringToPyDictItem(dict,"model",model);
879  PConvIntToPyDictItem(dict,"index",index+1);
880  PConvStringToPyDictItem(dict,"type",atype);
881  PConvStringToPyDictItem(dict,"name",at->name);
882  PConvStringToPyDictItem(dict,"resn",at->resn);
883  PConvStringToPyDictItem(dict,"resi",at->resi);
884  PConvIntToPyDictItem(dict,"resv",at->resv);
885  PConvStringToPyDictItem(dict,"chain",at->chain);
886  PConvStringToPyDictItem(dict,"alt",at->alt);
887  PConvStringToPyDictItem(dict,"segi",at->segi);
888  PConvStringToPyDictItem(dict,"ss",at->ssType);
889  PConvFloatToPyDictItem(dict,"vdw",at->vdw);
890  PConvFloatToPyDictItem(dict,"elec_radius",at->elec_radius);
891  {
892    char null_st[1] = "";
893    char *st = null_st;
894
895    if(at->textType) st = OVLexicon_FetchCString(G->Lexicon,at->textType);
896    PConvStringToPyDictItem(dict,"text_type",st);
897
898    st = null_st;
899    if(at->label) st = OVLexicon_FetchCString(G->Lexicon,at->label);
900    PConvStringToPyDictItem(dict,"label",st);
901  }
902  PConvStringToPyDictItem(dict,"elem",at->elem);
903  PConvIntToPyDictItem(dict,"geom",at->geom);
904  PConvIntToPyDictItem(dict,"valence",at->valence);
905  PConvIntToPyDictItem(dict,"rank",at->rank);
906  if(at->flags) {
907    sprintf(buffer,"%X",at->flags);
908    PConvStringToPyDictItem(dict,"flags",buffer);
909  } else {
910    PConvStringToPyDictItem(dict,"flags","0");
911  }
912  PConvFloatToPyDictItem(dict,"q",at->q);
913  PConvFloatToPyDictItem(dict,"b",at->b);
914  if(at->customType!=cAtomInfoNoType)
915    PConvIntToPyDictItem(dict,"numeric_type",at->customType);
916  else
917    PConvStringToPyDictItem(dict,"numeric_type","?"); 
918  PConvFloatToPyDictItem(dict,"partial_charge",at->partialCharge);
919  PConvIntToPyDictItem(dict,"formal_charge",at->formalCharge);
920  PConvIntToPyDictItem(dict,"color",at->color);
921  PConvIntToPyDictItem(dict,"cartoon",at->cartoon);
922  PConvIntToPyDictItem(dict,"ID",at->id);
923  PXDecRef(PyRun_String(expr,Py_single_input,P_inst_dict,dict));
924  if(PyErr_Occurred()) {
925    PyErr_Print();
926    result=false;
927  } else {
928    result=true;
929    if(!PConvPyObjectToStrMaxLen(PyDict_GetItemString(dict,"label"),
930                                 label,sizeof(OrthoLineType)-1))
931      result=false;
932    if(PyErr_Occurred()) {
933      PyErr_Print();
934      result=false;
935    }
936    if(result) {
937      if(at->label) {
938        OVLexicon_DecRef(G->Lexicon,at->label);
939      }
940      at->label = 0;
941     
942      if(label[0]) {
943        OVreturn_word ret = OVLexicon_GetFromCString(G->Lexicon,label);
944        if(OVreturn_IS_OK(ret)) {
945          /*printf("alloc'd %d [%s]\n",OVLexicon_GetNActive(G->Lexicon),label);*/
946          at->label = ret.word;
947        }
948      }
949    } else {
950      ErrMessage(G,"Label","Aborting on error. Labels may be incomplete.");
951    }
952  }
953  Py_DECREF(dict);
954  PUnblock(G);
955  return(result);
956}
957
958void PUnlockAPIAsGlut(PyMOLGlobals *G) /* must call with unblocked interpreter */
959{
960  PRINTFD(G,FB_Threads)
961    " PUnlockAPIAsGlut-DEBUG: entered as thread 0x%x\n",PyThread_get_thread_ident()
962    ENDFD;
963  PBlock(G);
964  PXDecRef(PyObject_CallFunction(P_unlock,NULL)); /* NOTE this may flush the command buffer! */
965  PLockStatus();
966  PyMOL_PopValidContext(G->PyMOL);
967  PUnlockStatus();
968  PUnlockGLUT();
969  PUnblock(G);
970}
971
972void PUnlockAPIAsGlutNoFlush(PyMOLGlobals *G) /* must call with unblocked interpreter */
973{
974  PRINTFD(G,FB_Threads)
975    " PUnlockAPIAsGlut-DEBUG: entered as thread 0x%x\n",PyThread_get_thread_ident()
976    ENDFD;
977  PBlock(G);
978  PXDecRef(PyObject_CallFunction(P_unlock,"i",-1)); /* prevents flushing of the buffer */
979  PLockStatus();
980  PyMOL_PopValidContext(G->PyMOL);
981  PUnlockStatus();
982  PUnlockGLUT();
983  PUnblock(G);
984}
985
986static int get_api_lock(PyMOLGlobals *G,int block_if_busy)
987{
988  int result = true;
989
990  if(block_if_busy) {
991   
992    PXDecRef(PyObject_CallFunction(P_lock,NULL));
993
994  } else { /* not blocking if PyMOL is busy */
995
996    PyObject *got_lock = PyObject_CallFunction(P_lock_attempt,NULL);
997   
998    if(got_lock) {
999      if(!PyInt_AsLong(got_lock)) {
1000        PLockStatus();
1001        if(PyMOL_GetBusy(G->PyMOL,false))
1002          result = false;
1003        PUnlockStatus();
1004       
1005        if(result) { /* didn't get lock, but not busy, so block and wait for lock */
1006          PXDecRef(PyObject_CallFunction(P_lock,NULL));
1007        }
1008      }
1009      Py_DECREF(got_lock);
1010    }
1011  }
1012  return result;
1013}
1014
1015int PLockAPIAsGlut(PyMOLGlobals *G,int block_if_busy)
1016{
1017  PRINTFD(G,FB_Threads)
1018    "*PLockAPIAsGlut-DEBUG: entered as thread 0x%x\n",PyThread_get_thread_ident()
1019    ENDFD;
1020
1021  PBlock(G);
1022
1023  PLockGLUT();
1024
1025  PLockStatus();
1026  PyMOL_PushValidContext(G->PyMOL);
1027  PUnlockStatus();
1028
1029  PRINTFD(G,FB_Threads)
1030    "#PLockAPIAsGlut-DEBUG: acquiring lock as thread 0x%x\n",PyThread_get_thread_ident()
1031    ENDFD;
1032 
1033  if(!get_api_lock(G,block_if_busy)) {
1034    PLockStatus();
1035    PyMOL_PopValidContext(G->PyMOL);
1036    PUnlockStatus();
1037    PUnlockGLUT();
1038    PUnblock(G);
1039    return false;/* busy -- so allow main to update busy status display (if any) */
1040  }
1041   
1042  while(P_glut_thread_keep_out) {
1043    /* IMPORTANT: keeps the glut thread out of an API operation... */
1044    /* NOTE: the keep_out variable can only be changed or read by the thread
1045       holding the API lock, therefore it is safe even through increment
1046       isn't atomic. */
1047    PRINTFD(G,FB_Threads)
1048      "-PLockAPIAsGlut-DEBUG: glut_thread_keep_out 0x%x\n",PyThread_get_thread_ident()
1049      ENDFD;
1050   
1051    PXDecRef(PyObject_CallFunction(P_unlock,"i",-1)); /* prevent buffer flushing */
1052#ifndef WIN32
1053    {
1054      struct timeval tv;
1055
1056      PUnblock(G);
1057      tv.tv_sec=0;
1058      tv.tv_usec=50000;
1059      select(0,NULL,NULL,NULL,&tv);
1060      PBlock(G);
1061    }
1062#else
1063/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
1064    PXDecRef(PyObject_CallFunction(P_sleep,"f",0.050));
1065/* END PROPRIETARY CODE SEGMENT */
1066#endif
1067
1068    if(!get_api_lock(G,block_if_busy)) {
1069      /* return false-- allow main to update busy status display (if any) */
1070      PLockStatus();
1071      PyMOL_PopValidContext(G->PyMOL);
1072      PUnlockStatus();
1073      PUnlockGLUT();
1074      PUnblock(G);
1075      return false;
1076    }
1077  }
1078
1079
1080  PUnblock(G); /* API is now locked, so we can free up Python...*/
1081
1082  PRINTFD(G,FB_Threads)
1083    "=PLockAPIAsGlut-DEBUG: acquired\n"
1084    ENDFD;
1085  return true;
1086}
1087
1088/* THESE CALLS ARE REQUIRED FOR MONOLITHIC COMPILATION TO SUCCEED UNDER WINDOWS. */
1089#ifndef _PYMOL_ACTIVEX
1090#ifndef _PYMOL_EMBEDDED
1091void    initExtensionClass(void);
1092void    initsglite(void);
1093void  init_champ(void);
1094void    init_opengl(void);
1095void    init_opengl_num(void);
1096void    init_glu(void);
1097void    init_glu_num(void);
1098void    init_glut(void);
1099void    initopenglutil(void);
1100void    initopenglutil_num(void);
1101#endif
1102#endif
1103
1104#ifdef _PYMOL_MONOLITHIC
1105#ifndef _PYMOL_ACTIVEX
1106#ifndef _PYMOL_EMBEDDED
1107/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
1108#ifdef WIN32
1109void    init_numpy();
1110void    initmultiarray();
1111void    initarrayfns();
1112void    initlapack_lite();
1113void    initumath();
1114void    initranlib();
1115void  init_champ();
1116#endif
1117/* END PROPRIETARY CODE SEGMENT */
1118#endif
1119#endif
1120#endif
1121
1122#ifdef _PYMOL_MONOLITHIC
1123#ifndef _PYMOL_ACTIVEX
1124#ifndef _PYMOL_EMBEDDED
1125void    initExtensionClass(void);
1126void    initsglite(void);
1127void  init_champ(void);
1128void    init_opengl(void);
1129void    init_opengl_num(void);
1130void    init_glu(void);
1131void    init_glu_num(void);
1132void    init_glut(void);
1133void    initopenglutil(void);
1134void    initopenglutil_num(void);
1135#endif
1136#endif
1137#endif
1138/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
1139#ifdef WIN32
1140static int IsSecurityRequired()
1141{
1142  DWORD WindowsVersion = GetVersion();
1143  DWORD WindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(WindowsVersion)));
1144  DWORD WindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(WindowsVersion)));
1145
1146  if (WindowsVersion >= 0x80000000) return FALSE;
1147 
1148  return TRUE;
1149}
1150#endif
1151/* END PROPRIETARY CODE SEGMENT */
1152
1153void PSetupEmbedded(PyMOLGlobals *G,int argc,char **argv)
1154{
1155  /* This routine is called if we are running with an embedded Python interpreter */
1156  PyObject *args, *pymol;
1157
1158/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
1159#ifdef WIN32
1160   
1161  { /* automatically hide the window if this process
1162       was started as a vanilla console application */
1163    HWND hwndFound;         
1164    if(hwndFound=FindWindow(NULL, argv[0])) {
1165      ShowWindow(hwndFound,SW_HIDE);
1166    }
1167  }
1168   
1169  {/* if PYMOL_PATH and/or PYTHONHOME isn't in the environment coming
1170      in, then the user may simply have clicked PyMOL.exe, in which
1171      case we need to consult the registry regarding the location of
1172      the install */
1173   
1174    /* embedded version of PyMOL currently ships with Python 2.4 */
1175#define EMBEDDED_PYTHONHOME "\\py24"
1176       
1177    OrthoLineType path_buffer;
1178    static char line1[8092];
1179    static char line2[8092];
1180    HKEY phkResult;
1181    int lpcbData;
1182    int lpType = REG_SZ;
1183    int r1,r2;
1184    char *pymol_path;
1185    char *pythonhome;
1186    int pythonhome_set = false;
1187    int restart_flag = false;
1188       
1189       
1190    pymol_path = getenv("PYMOL_PATH");
1191    pythonhome = getenv("PYTHONHOME");
1192    if((!pymol_path)||(!pythonhome)) {
1193      lpcbData = sizeof(OrthoLineType)-1;
1194      r1=RegOpenKeyEx(HKEY_CLASSES_ROOT,
1195                      "Software\\DeLano Scientific\\PyMOL\\PYMOL_PATH",
1196                      0,KEY_EXECUTE,&phkResult);
1197      if(r1!=ERROR_SUCCESS) {
1198        r1=RegOpenKeyEx(HKEY_CURRENT_USER,
1199                        "Software\\DeLano Scientific\\PyMOL\\PYMOL_PATH",
1200                        0,KEY_EXECUTE,&phkResult);
1201      } 
1202      if(r1==ERROR_SUCCESS) {
1203        r2 = RegQueryValueEx(phkResult,"",NULL,
1204                             &lpType,path_buffer,&lpcbData);
1205        if (r2==ERROR_SUCCESS) {
1206          /* use environment variable PYMOL_PATH first, registry entry
1207             second */
1208          if(!pymol_path) {
1209            strcpy(line1,"PYMOL_PATH=");
1210            strcat(line1,path_buffer);
1211            _putenv(line1);
1212            if(!pythonhome) { /* only set PYTHONHOME if already
1213                                 setting new PYMOL_PATH */
1214              pythonhome_set = true;
1215              strcpy(line2,"PYTHONHOME=");
1216              strcat(line2,path_buffer);
1217              strcat(line2,EMBEDDED_PYTHONHOME);
1218              restart_flag = true;
1219              _putenv(line2);
1220            }
1221          }
1222        }
1223        RegCloseKey(phkResult);
1224      }
1225      /* this allows us to just specify PYMOL_PATH with no registry entries */
1226      if((!pythonhome_set)&&(pymol_path)&&(!pythonhome)) {
1227        strcpy(line2,"PYTHONHOME=");
1228        strcat(line2,pymol_path);
1229        strcat(line2,EMBEDDED_PYTHONHOME);
1230        _putenv(line2);
1231        restart_flag = true;
1232      }
1233    }
1234    if(restart_flag && getenv("PYMOL_PATH") && getenv("PYTHONHOME")) {
1235           
1236      /* now that we have the environment defined, restart the process
1237       * so that Python can use the new environment.  If we don't do
1238       * this, then Python won't see the new environment vars. Why not? */
1239
1240      /* note that we use CreateProcesss to launch the console
1241       * application instead of exec or spawn in order to hide the
1242       * console window. Otherwise a console window might appear, and
1243       * that would suck. */
1244           
1245      char command[8092];
1246      static char cmd_line[8092];
1247      char *p,*q;
1248      int a;
1249           
1250      /* copy arguments, installing quotes around them */
1251           
1252      sprintf(command,"%s\\pymol.exe",getenv("PYMOL_PATH"));
1253      p = cmd_line;
1254           
1255      sprintf(p,"\"%s\"",command);
1256      p+=strlen(p);
1257      *(p++)=' ';
1258      *p=0;
1259           
1260      for(a=1;a<=argc;a++) {
1261        q = argv[a];
1262        if(q) {
1263          if(*q!='"') { /* add quotes if not present */
1264            *(p++)='"';
1265            while(*q) {
1266              *(p++)=*(q++);
1267            }
1268            *(p++)='"';
1269          } else {
1270            while(*q) {
1271              *(p++)=*(q++);
1272            }
1273          }
1274          *(p++)=32;
1275          *p=0;
1276        }
1277      }
1278
1279      {
1280        LPSECURITY_ATTRIBUTES lpSA = NULL;
1281        PSECURITY_DESCRIPTOR lpSD = NULL;
1282        STARTUPINFO si;
1283        PROCESS_INFORMATION pi;
1284        HANDLE hProcess = GetCurrentProcess();
1285               
1286        ZeroMemory(&si, sizeof(STARTUPINFO));
1287        si.cb = sizeof(STARTUPINFO);
1288        si.dwFlags = STARTF_USESHOWWINDOW;
1289        si.wShowWindow = SW_HIDE;
1290               
1291        if(IsSecurityRequired())
1292          {
1293            lpSD = GlobalAlloc(GPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
1294            InitializeSecurityDescriptor(lpSD, SECURITY_DESCRIPTOR_REVISION);
1295            SetSecurityDescriptorDacl(lpSD, -1, 0, 0);
1296                   
1297            lpSA = GlobalAlloc(GPTR, sizeof(SECURITY_ATTRIBUTES));
1298            lpSA->nLength = sizeof(SECURITY_ATTRIBUTES);
1299            lpSA->lpSecurityDescriptor = lpSD;
1300            lpSA->bInheritHandle = TRUE;
1301          }
1302               
1303        if(CreateProcess(NULL, (LPTSTR)cmd_line, lpSA, NULL, TRUE,
1304                         0, NULL, NULL, &si, &pi)) {
1305          WaitForSingleObject(pi.hProcess, INFINITE);
1306        }
1307        if (lpSA != NULL) GlobalFree(lpSA);
1308        if (lpSD != NULL) GlobalFree(lpSD);
1309        _exit(0);
1310      }
1311    }
1312  }
1313
1314#endif
1315/* END PROPRIETARY CODE SEGMENT */
1316
1317
1318  /* compatibility for old compile-time defines */
1319
1320#ifdef _PYMOL_SETUP_PY21
1321#ifndef _PYMOL_SETUP_PY_EXT
1322#define _PYMOL_SETUP_PY_EXT
1323#endif
1324#endif
1325#ifdef _PYMOL_SETUP_PY22
1326#ifndef _PYMOL_SETUP_PY_EXT
1327#define _PYMOL_SETUP_PY_EXT
1328#endif
1329#endif
1330#ifdef _PYMOL_SETUP_PY23
1331#ifndef _PYMOL_SETUP_PY_EXT
1332#define _PYMOL_SETUP_PY_EXT
1333#endif
1334#endif
1335#ifdef _PYMOL_SETUP_PY24
1336#ifndef _PYMOL_SETUP_PY_EXT
1337#define _PYMOL_SETUP_PY_EXT
1338#endif
1339#endif
1340#ifdef _PYMOL_SETUP_PY25
1341#ifndef _PYMOL_SETUP_PY_EXT
1342#define _PYMOL_SETUP_PY_EXT
1343#endif
1344#endif
1345
1346  /* should we set up PYTHONHOME in the ext directory? */
1347
1348#ifdef _PYMOL_SETUP_PY_EXT
1349  {
1350    static char line1[8092];
1351    static char line2[8092];
1352
1353    if(!getenv("PYMOL_PATH")) { /* if PYMOL_PATH isn't defined...*/
1354   
1355      /* was our startup path absolute? */
1356   
1357      if((argc>0) && (argv[0][0]=='/')) {
1358        /* PYMOL was started with an absolute path, so try using that... */
1359        char *p;
1360        strcpy(line1,"PYMOL_PATH=");
1361        strcat(line1,argv[0]);
1362        p=line1 + strlen(line1);
1363        while(*p!='/') {
1364          *p=0;
1365          p--;
1366        }
1367        *p=0;
1368        putenv(line1);
1369      } else if((argc>0) && getenv("PWD") && ((argv[0][0]=='.')||(strstr(argv[0],"/")))) {
1370        /* was the path relative? */
1371        char *p;
1372        strcpy(line1,"PYMOL_PATH=");
1373        strcat(line1,getenv("PWD"));
1374        strcat(line1,"/");
1375        strcat(line1,argv[0]);
1376        p=line1 + strlen(line1);
1377        while(*p!='/') {
1378          *p=0;
1379          p--;
1380        }
1381        *p=0;
1382        putenv(line1);
1383      } else { /* otherwise, just try using the current working directory */
1384        if(getenv("PWD")) {
1385          strcpy(line1,"PYMOL_PATH=");
1386          strcat(line1,getenv("PWD"));
1387          putenv(line1);
1388        }
1389      }
1390    }
1391 
1392    /* now set PYTHONHOME so that we use the right binary libraries for
1393       this executable */
1394
1395    if(getenv("PYMOL_PATH")) {
1396      strcpy(line2,"PYTHONHOME=");
1397      strcat(line2,getenv("PYMOL_PATH"));
1398      strcat(line2,"/ext");
1399      putenv(line2);
1400    }
1401  }
1402#endif
1403
1404#ifndef _PYMOL_ACTIVEX
1405#ifndef _PYMOL_EMBEDDED
1406  Py_Initialize();
1407  PyEval_InitThreads();
1408  PyUnicode_SetDefaultEncoding("utf-8"); /* is this safe & legal? */
1409
1410#endif
1411#endif
1412
1413  init_cmd();
1414#ifdef _PYMOL_MONOLITHIC
1415#ifndef _PYMOL_ACTIVEX
1416#ifndef _PYMOL_EMBEDDED
1417  initExtensionClass();
1418  initsglite();
1419  /* initialize champ */
1420  init_champ();
1421/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
1422#ifdef WIN32
1423  /* initialize numeric python */
1424  init_numpy();
1425  initmultiarray();
1426  initarrayfns();
1427  initlapack_lite();
1428  initumath();
1429  initranlib();
1430#endif
1431/* END PROPRIETARY CODE SEGMENT */
1432  init_opengl();
1433  init_opengl_num();
1434  init_glu();
1435  init_glu_num();
1436  init_glut();
1437  initopenglutil();
1438  initopenglutil_num();
1439#endif
1440#endif
1441#endif
1442  PyRun_SimpleString("import os\n");
1443  PyRun_SimpleString("import sys\n");
1444/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
1445#ifdef WIN32
1446#if 0
1447  {
1448    OrthoLineType path_buffer,command;
1449    HKEY phkResult;
1450    int lpcbData;
1451    int lpType = REG_SZ;
1452    int r1,r2;
1453 
1454    lpcbData = sizeof(OrthoLineType)-1;
1455    r1=RegOpenKeyEx(HKEY_CLASSES_ROOT,"Software\\DeLano Scientific\\PyMOL\\PYMOL_PATH",0,KEY_EXECUTE,&phkResult);
1456    if(r1==ERROR_SUCCESS) {
1457      r2 = RegQueryValueEx(phkResult,"",NULL,&lpType,path_buffer,&lpcbData);
1458      if (r2==ERROR_SUCCESS) {
1459        /* use environment variable PYMOL_PATH first, registry entry second */
1460        sprintf(command,"_registry_pymol_path = r'''%s'''\n",path_buffer);
1461        PyRun_SimpleString(command);
1462        PyRun_SimpleString("if not os.environ.has_key('PYMOL_PATH'): os.environ['PYMOL_PATH']=_registry_pymol_path\n");
1463      }
1464      RegCloseKey(phkResult);
1465    }
1466  }
1467#endif
1468  PyRun_SimpleString("if not os.environ.has_key('PYMOL_PATH'): os.environ['PYMOL_PATH']=os.getcwd()\n");
1469#endif
1470/* END PROPRIETARY CODE SEGMENT */
1471
1472#ifdef _PYMOL_SETUP_TCLTK83
1473  /* used by semistatic pymol */
1474  PyRun_SimpleString("if os.path.exists(os.environ['PYMOL_PATH']+'/ext/lib/tcl8.3'): os.environ['TCL_LIBRARY']=os.environ['PYMOL_PATH']+'/ext/lib/tcl8.3'\n");
1475  PyRun_SimpleString("if os.path.exists(os.environ['PYMOL_PATH']+'/ext/lib/tk8.3'): os.environ['TK_LIBRARY']=os.environ['PYMOL_PATH']+'/ext/lib/tk8.3'\n");
1476#endif
1477
1478#ifdef _PYMOL_SETUP_TCLTK84
1479  /* used by semistatic pymol */
1480  PyRun_SimpleString("if os.path.exists(os.environ['PYMOL_PATH']+'/ext/lib/tcl8.4'): os.environ['TCL_LIBRARY']=os.environ['PYMOL_PATH']+'/ext/lib/tcl8.4'\n");
1481  PyRun_SimpleString("if os.path.exists(os.environ['PYMOL_PATH']+'/ext/lib/tk8.4'): os.environ['TK_LIBRARY']=os.environ['PYMOL_PATH']+'/ext/lib/tk8.4'\n");
1482#endif
1483
1484#if 0
1485  /* no longer necessary since we're setting PYTHONHOME */
1486#ifdef _PYMOL_SETUP_PY21
1487  /* used by semistatic pymol */
1488  PyRun_SimpleString("import string");
1489  PyRun_SimpleString("sys.path=filter(lambda x:string.find(x,'static/ext-static')<0,sys.path)"); /* clean bogus entries in sys.path */
1490#endif
1491#ifdef _PYMOL_SETUP_PY22
1492  /* used by semistatic pymol */
1493  PyRun_SimpleString("import string");
1494  PyRun_SimpleString("sys.path=filter(lambda x:string.find(x,'static/ext')<0,sys.path)"); /* clean bogus entries in sys.path */
1495#endif
1496#ifdef _PYMOL_SETUP_PY23
1497  /* used by semistatic pymol */
1498  PyRun_SimpleString("import string");
1499  PyRun_SimpleString("sys.path=filter(lambda x:string.find(x,'static/ext')<0,sys.path)"); /* clean bogus entries in sys.path */
1500#endif
1501#endif
1502/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
1503#ifdef WIN32
1504  PyRun_SimpleString("if (os.environ['PYMOL_PATH']+'/modules') not in sys.path: sys.path.insert(0,os.environ['PYMOL_PATH']+'/modules')\n");
1505#endif
1506/* END PROPRIETARY CODE SEGMENT */
1507
1508  P_main = PyImport_AddModule("__main__");
1509  if(!P_main) ErrFatal(G,"PyMOL","can't find '__main__'");
1510
1511  /* inform PyMOL's other half that we're launching embedded-style */
1512  PyObject_SetAttrString(P_main,"pymol_launch",PyInt_FromLong(4));
1513
1514  args = PConvStringListToPyList(argc,argv); /* prepare our argument list */
1515  if(!args) ErrFatal(G,"PyMOL","can't process arguments.");
1516
1517  /* copy arguments to __main__.pymol_argv */
1518  PyObject_SetAttrString(P_main,"pymol_argv",args);
1519 
1520  PyRun_SimpleString("if (os.environ['PYMOL_PATH']+'/modules') not in sys.path: sys.path.insert(0,os.environ['PYMOL_PATH']+'/modules')\n"); /* needed for semistatic pymol */
1521
1522  PyRun_SimpleString("import pymol"); /* create the global PyMOL namespace */
1523
1524  pymol = PyImport_AddModule("pymol"); /* get it */
1525  if(!pymol) ErrFatal(G,"PyMOL","can't find module 'pymol'");
1526
1527}
1528
1529void PGetOptions(CPyMOLOptions *rec)
1530{
1531  PyObject *pymol,*invocation,*options;
1532  char *load_str;
1533
1534  pymol = PyImport_AddModule("pymol"); /* get it */
1535  if(!pymol) {fprintf(stderr,"PyMOL-ERROR: can't find module 'pymol'"); exit(EXIT_FAILURE);}
1536
1537  invocation = PyObject_GetAttrString(pymol,"invocation"); /* get a handle to the invocation module */
1538  if(!invocation) {fprintf(stderr,"PyMOL-ERROR: can't find module 'invocation'"); exit(EXIT_FAILURE);}
1539
1540  options = PyObject_GetAttrString(invocation,"options");
1541  if(!options) {fprintf(stderr,"PyMOL-ERROR: can't get 'invocation.options'.");exit(EXIT_FAILURE);}
1542
1543  rec->pmgui = ! PyInt_AsLong(PyObject_GetAttrString(options,"no_gui"));
1544  rec->internal_gui = PyInt_AsLong(PyObject_GetAttrString(options,"internal_gui"));
1545  rec->internal_feedback = PyInt_AsLong(PyObject_GetAttrString(options,"internal_feedback"));
1546  rec->show_splash = PyInt_AsLong(PyObject_GetAttrString(options,"show_splash"));
1547  rec->security = PyInt_AsLong(PyObject_GetAttrString(options,"security"));
1548  rec->game_mode = PyInt_AsLong(PyObject_GetAttrString(options,"game_mode"));
1549  rec->force_stereo = PyInt_AsLong(PyObject_GetAttrString(options,"force_stereo"));
1550  rec->winX = PyInt_AsLong(PyObject_GetAttrString(options,"win_x"));
1551  rec->winY = PyInt_AsLong(PyObject_GetAttrString(options,"win_y"));
1552  rec->winPX = PyInt_AsLong(PyObject_GetAttrString(options,"win_px"));
1553  rec->winPY = PyInt_AsLong(PyObject_GetAttrString(options,"win_py"));
1554  rec->blue_line = PyInt_AsLong(PyObject_GetAttrString(options,"blue_line"));
1555  rec->external_gui = PyInt_AsLong(PyObject_GetAttrString(options,"external_gui"));
1556  rec->siginthand = PyInt_AsLong(PyObject_GetAttrString(options,"sigint_handler"));
1557  rec->reuse_helper = PyInt_AsLong(PyObject_GetAttrString(options,"reuse_helper"));
1558  rec->auto_reinitialize = PyInt_AsLong(PyObject_GetAttrString(options,"auto_reinitialize"));
1559  rec->keep_thread_alive = PyInt_AsLong(PyObject_GetAttrString(options,"keep_thread_alive"));
1560  rec->quiet = PyInt_AsLong(PyObject_GetAttrString(options,"quiet"));
1561#ifdef _IPYMOL
1562  rec->incentive_product = true;
1563#else
1564  rec->incentive_product = PyInt_AsLong(PyObject_GetAttrString(options,"incentive_product"));
1565#endif
1566  rec->multisample = PyInt_AsLong(PyObject_GetAttrString(options,"multisample"));
1567  rec->window_visible = PyInt_AsLong(PyObject_GetAttrString(options,"window_visible"));
1568  rec->read_stdin = PyInt_AsLong(PyObject_GetAttrString(options,"read_stdin"));
1569  rec->presentation = PyInt_AsLong(PyObject_GetAttrString(options,"presentation"));
1570  rec->defer_builds_mode = PyInt_AsLong(PyObject_GetAttrString(options,"defer_builds_mode"));
1571  rec->full_screen = PyInt_AsLong(PyObject_GetAttrString(options,"full_screen"));
1572  load_str = PyString_AsString(PyObject_GetAttrString(options,"after_load_script"));
1573  rec->sphere_mode = PyInt_AsLong(PyObject_GetAttrString(options,"sphere_mode"));
1574  rec->stereo_capable = PyInt_AsLong(PyObject_GetAttrString(options,"stereo_capable"));
1575  rec->passive_stereo= PyInt_AsLong(PyObject_GetAttrString(options,"passive_stereo"));
1576  rec->zoom_mode= PyInt_AsLong(PyObject_GetAttrString(options,"zoom_mode"));
1577  if(load_str) {
1578    if(load_str[0]) {
1579      UtilNCopy(rec->after_load_script,load_str,PYMOL_MAX_OPT_STR);
1580    }
1581  }
1582  if(PyErr_Occurred()) {
1583    PyErr_Print();
1584  }
1585}
1586
1587void PRunStringModule(PyMOLGlobals *G,char *str) /* runs a string in the namespace of the pymol instance */
1588{
1589  PXDecRef(PyObject_CallFunction(G->P_inst->exec,"Os",P_pymol,str));
1590}
1591
1592void PRunStringInstance(PyMOLGlobals *G,char *str) /* runs a string in the namespace of the pymol instance */
1593{
1594  PXDecRef(PyObject_CallFunction(G->P_inst->exec,"Os",G->P_inst->obj,str));
1595}
1596
1597void PInit(PyMOLGlobals *G,int global_instance)
1598{
1599  PyObject *sys,*pcatch;
1600  int a;
1601
1602#ifdef PYMOL_NEW_THREADS
1603   PyEval_InitThreads();
1604#endif
1605
1606/* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
1607#ifdef WIN32
1608#ifdef _PYMOL_MONOLITHIC
1609#ifndef _PYMOL_ACTIVEX
1610#ifndef _PYMOL_EMBEDDED
1611#define _PYMOL_INIT_MODULES
1612#endif
1613#endif
1614#endif
1615#endif
1616/* END PROPRIETARY CODE SEGMENT */
1617
1618#ifdef _PYMOL_INIT_MODULES
1619        /* Win32 module build: includes pyopengl, numpy, and sglite */
1620        /* sglite */
1621        initExtensionClass();
1622        initsglite();
1623    init_champ();
1624        /* initialize numeric python */
1625        init_numpy();
1626        initmultiarray();
1627        initarrayfns();
1628        initlapack_lite();
1629        initumath();
1630        initranlib();
1631        /* initialize PyOpenGL */
1632    init_opengl();
1633    init_opengl_num();
1634    init_glu();
1635    init_glu_num();
1636    init_glut();
1637    initopenglutil();
1638        initopenglutil_num();
1639#endif
1640
1641
1642  for(a=0;a<MAX_SAVED_THREAD;a++) {
1643    SavedThread[a].id=-1;
1644  }
1645
1646  if(global_instance) {
1647    PCatchInit();   /* setup standard-output catch routine */
1648  }
1649
1650/* assumes that pymol module has been loaded via Python or PyRun_SimpleString */
1651
1652  P_pymol = PyImport_AddModule("pymol"); /* get it */
1653  if(!P_pymol) ErrFatal(G,"PyMOL","can't find module 'pymol'");
1654  P_pymol_dict = PyModule_GetDict(P_pymol);
1655  if(!P_pymol_dict) ErrFatal(G,"PyMOL","can't find globals for 'pymol'");
1656
1657  if(global_instance) { /* if global singleton PyMOL... */
1658    G->P_inst = Calloc(CP_inst,1);
1659    G->P_inst->obj = P_pymol;
1660    G->P_inst->dict = P_pymol_dict;
1661  }
1662 
1663  {
1664    G->P_inst->exec = PyDict_GetItemString(P_pymol_dict,"exec_str");
1665    if(!G->P_inst->exec) ErrFatal(G,"PyMOL","can't find 'pymol.exec_str()'");
1666
1667    sys = PyDict_GetItemString(P_pymol_dict,"sys");
1668    if(!sys) ErrFatal(G,"PyMOL","can't find 'pymol.sys'");
1669
1670    if(global_instance) {
1671
1672      /* implies global singleton pymol, so set up the global handle */
1673      PyDict_SetItemString(P_pymol_dict,"_COb",PyCObject_FromVoidPtr((void*)&TempPyMOLGlobals,NULL));
1674
1675      pcatch = PyImport_AddModule("pcatch");
1676      if(!pcatch) ErrFatal(G,"PyMOL","can't find module 'pcatch'");
1677      PyObject_SetAttrString(sys,"stdout",pcatch);
1678      PyObject_SetAttrString(sys,"stderr",pcatch);
1679    }
1680
1681    PRunStringModule(G,"import traceback\n"); 
1682    P_traceback = PyDict_GetItemString(P_pymol_dict,"traceback");
1683    if(!P_traceback) ErrFatal(G,"PyMOL","can't find 'traceback'");
1684
1685    PRunStringModule(G,"import cmd\n"); 
1686    P_cmd = PyDict_GetItemString(P_pymol_dict,"cmd");
1687    if(!P_cmd) ErrFatal(G,"PyMOL","can't find 'cmd'");
1688
1689    if(global_instance) {
1690      /* implies global singleton pymol, so set up the global handle */
1691      PyObject_SetAttrString(P_cmd,"_COb",PyCObject_FromVoidPtr((void*)&TempPyMOLGlobals,NULL));
1692
1693      /* cmd module is itself the api for the global PyMOL instance */
1694      G->P_inst->cmd = P_cmd;
1695    }
1696
1697    PyObject_SetAttrString(G->P_inst->cmd,"_pymol",G->P_inst->obj);
1698
1699    /* right now, all locks are global -- eventually some of these may
1700       become instance-specific in order to improve concurrency */
1701
1702    P_lock = PyObject_GetAttrString(P_cmd,"lock");
1703    if(!P_lock) ErrFatal(G,"PyMOL","can't find 'cmd.lock()'");
1704
1705    P_lock_attempt = PyObject_GetAttrString(P_cmd,"lock_attempt");
1706    if(!P_lock_attempt) ErrFatal(G,"PyMOL","can't find 'cmd.lock_attempt()'");
1707
1708    P_unlock = PyObject_GetAttrString(P_cmd,"unlock");
1709    if(!P_unlock) ErrFatal(G,"PyMOL","can't find 'cmd.unlock()'");
1710
1711    P_lock_c = PyObject_GetAttrString(P_cmd,"lock_c");
1712    if(!P_lock_c) ErrFatal(G,"PyMOL","can't find 'cmd.lock_c()'");
1713
1714    P_unlock_c = PyObject_GetAttrString(P_cmd,"unlock_c");
1715    if(!P_unlock_c) ErrFatal(G,"PyMOL","can't find 'cmd.unlock_c()'");
1716
1717    P_lock_status = PyObject_GetAttrString(P_cmd,"lock_status");
1718    if(!P_lock_status) ErrFatal(G,"PyMOL","can't find 'cmd.lock_status()'");
1719
1720    P_lock_status_attempt = PyObject_GetAttrString(P_cmd,"lock_status_attempt");
1721    if(!P_lock_status_attempt) ErrFatal(G,"PyMOL","can't find 'cmd.lock_status_attempt()'");
1722
1723    P_unlock_status = PyObject_GetAttrString(P_cmd,"unlock_status");
1724    if(!P_unlock_status) ErrFatal(G,"PyMOL","can't find 'cmd.unlock_status()'");
1725
1726    P_lock_glut = PyObject_GetAttrString(P_cmd,"lock_glut");
1727    if(!P_lock_glut) ErrFatal(G,"PyMOL","can't find 'cmd.lock_glut()'");
1728
1729    P_unlock_glut = PyObject_GetAttrString(P_cmd,"unlock_glut");
1730    if(!P_unlock_glut) ErrFatal(G,"PyMOL","can't find 'cmd.unlock_glut()'");
1731   
1732    /* 'do' command */
1733
1734    G->P_inst->cmd_do = PyObject_GetAttrString(G->P_inst->cmd,"do");
1735    if(!G->P_inst->cmd_do) ErrFatal(G,"PyMOL","can't find 'cmd.do()'");
1736
1737    /* invariant stuff */
1738
1739    PRunStringModule(G,"import menu\n"); 
1740    P_menu = PyDict_GetItemString(P_pymol_dict,"menu");
1741    if(!P_menu) ErrFatal(G,"PyMOL","can't find module 'menu'");
1742
1743    PRunStringModule(G,"import setting\n"); 
1744    P_setting = PyDict_GetItemString(P_pymol_dict,"setting");
1745    if(!P_setting) ErrFatal(G,"PyMOL","can't find module 'setting'");
1746
1747    PRunStringModule(G,"import povray\n"); 
1748    P_povray = PyDict_GetItemString(P_pymol_dict,"povray");
1749    if(!P_povray) ErrFatal(G,"PyMOL","can't find module 'povray'");
1750
1751#ifdef _PYMOL_XRAY
1752    PRunStringModule(G,"import xray\n"); 
1753    P_xray = PyDict_GetItemString(P_pymol_dict,"xray");
1754    if(!P_xray) ErrFatal(G,"PyMOL","can't find module 'xray'");
1755#endif
1756
1757    /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
1758#ifdef WIN32
1759    PRunStringModule(G,"import time\n"); 
1760    P_time = PyDict_GetItemString(P_pymol_dict,"time");
1761    if(!P_time) ErrFatal(G,"PyMOL","can't find module 'time'");
1762
1763    P_sleep = PyObject_GetAttrString(P_time,"sleep");
1764    if(!P_sleep) ErrFatal(G,"PyMOL","can't find 'time.sleep()'");
1765#endif
1766    /* END PROPRIETARY CODE SEGMENT */
1767
1768    PRunStringModule(G,"import parser\n"); 
1769    P_parser = PyDict_GetItemString(P_pymol_dict,"parser");
1770    if(!P_parser) ErrFatal(G,"PyMOL","can't find module 'parser'");
1771
1772    {
1773      PyObject *fn_closure = PyObject_GetAttrString(P_parser,"new_parse_closure");
1774      G->P_inst->parse = PyObject_CallFunction(fn_closure,"O",G->P_inst->cmd);
1775      PXDecRef(fn_closure);
1776      if(!G->P_inst->parse) ErrFatal(G,"PyMOL","can't create 'parse' function closure");
1777    }
1778
1779    {
1780      PyObject *fn_closure = PyObject_GetAttrString(P_parser,"new_complete_closure");
1781      G->P_inst->complete = PyObject_CallFunction(fn_closure,"O",G->P_inst->cmd);
1782      PXDecRef(fn_closure);
1783      if(!G->P_inst->complete) ErrFatal(G,"PyMOL","can't create 'complete' function closure");
1784    }
1785
1786    PRunStringModule(G,"import chempy");
1787    P_chempy = PyDict_GetItemString(P_pymol_dict,"chempy");
1788    if(!P_chempy) ErrFatal(G,"PyMOL","can't find 'chempy'");
1789
1790    PRunStringModule(G,"from chempy.bonds import bonds"); /* load bond dictionary */
1791
1792    PRunStringModule(G,"from chempy import models");
1793    P_models = PyDict_GetItemString(P_pymol_dict,"models");
1794    if(!P_models) ErrFatal(G,"PyMOL","can't find 'chempy.models'");
1795
1796    PRunStringModule(G,"import util\n"); 
1797    PRunStringModule(G,"import preset\n"); 
1798    PRunStringModule(G,"import contrib\n");
1799
1800    PRunStringModule(G,"import string\n");
1801
1802    /* backwards compatibility */
1803
1804    PRunStringModule(G,"pm = cmd\n"); 
1805    PRunStringModule(G,"pmu = util\n"); 
1806
1807    PRunStringModule(G,"glutThread = thread.get_ident()");
1808
1809    P_glut_thread_id = PyThread_get_thread_ident();
1810
1811#ifndef WIN32
1812    if(G->Option->siginthand) {
1813      signal(SIGINT,my_interrupt);
1814    }
1815#endif
1816
1817    /* required environment variables */
1818
1819    PyRun_SimpleString("import os");
1820    PyRun_SimpleString(
1821                       "if not os.environ.has_key('PYMOL_DATA'): os.environ['PYMOL_DATA']=os.environ['PYMOL_PATH']+'/data'");
1822    PyRun_SimpleString(
1823                       "os.environ['TUT']=os.environ['PYMOL_DATA']+'/tut'");
1824
1825    PyRun_SimpleString(
1826                       "if not os.environ.has_key('PYMOL_SCRIPTS'): os.environ['PYMOL_SCRIPTS']=os.environ['PYMOL_PATH']+'/scripts'");
1827
1828  }
1829}
1830
1831int PPovrayRender(PyMOLGlobals *G,char *header,char *inp,char *file,int width,int height,int antialias)
1832{
1833  PyObject *result;
1834  int ok;
1835  PBlock(G);
1836  result = PyObject_CallMethod(P_povray,"render_from_string","sssiii",header,inp,file,width,height,antialias);
1837  ok = PyObject_IsTrue(result);
1838  Py_DECREF(result);
1839  PUnblock(G);
1840  return(ok);
1841}
1842
1843void PSGIStereo(PyMOLGlobals *G,int flag)
1844{
1845  int blocked;
1846  blocked = PAutoBlock(G);
1847  if(flag)
1848    PRunStringModule(G,"cmd._sgi_stereo(1)");
1849  else
1850    PRunStringModule(G,"cmd._sgi_stereo(0)");
1851  if(blocked) PUnblock(G);
1852}
1853
1854void PFree(void)
1855{
1856}
1857
1858void PExit(PyMOLGlobals *G,int code)
1859{
1860  ExecutiveDelete(G,"all");
1861  PBlock(G);
1862#ifndef _PYMOL_NO_MAIN
1863  MainFree();
1864#endif
1865
1866  /* we're having trouble with threading errors after calling Py_Exit,
1867     so for the time being, let's just take the process down at this
1868     point, instead of allowing PyExit to be called. */
1869
1870  exit(EXIT_SUCCESS);                       
1871
1872  Py_Exit(code);
1873}
1874
1875void PParse(PyMOLGlobals *G,char *str)
1876{
1877  OrthoCommandIn(G,str);
1878}
1879
1880void PDo(PyMOLGlobals *G,char *str) /* assumes we already hold the re-entrant API lock */
1881{
1882  int blocked;
1883  blocked = PAutoBlock(G);
1884  Py_XDECREF(PyObject_CallFunction(G->P_inst->cmd_do,"s",str));
1885  PAutoUnblock(G,blocked);
1886}
1887
1888void PLog(PyMOLGlobals *G,char *str,int format)
1889     /* general log routine can write PML
1890        or PYM commands to appropriate log file */
1891
1892  int mode;
1893  int a;
1894  int blocked;
1895  PyObject *log;
1896  OrthoLineType buffer="";
1897  mode = (int)SettingGet(G,cSetting_logging);
1898  if(mode)
1899    {
1900      blocked = PAutoBlock(G);
1901      log = PyDict_GetItemString(P_pymol_dict,P_log_file_str);
1902      if(log&&(log!=Py_None)) {
1903        if(format==cPLog_no_flush) {
1904          PyObject_CallMethod(log,"write","s",str); /* maximize responsiveness (for real-time) */
1905        } else {
1906          switch(mode) {
1907          case cPLog_pml: /* .pml file */
1908            switch(format) {
1909            case cPLog_pml_lf:
1910              strcpy(buffer,str);
1911              break;
1912            case cPLog_pml:
1913            case cPLog_pym:
1914              strcpy(buffer,str);
1915              strcat(buffer,"\n");
1916              break;
1917            }
1918            break;
1919          case cPLog_pym: /* .pym file */
1920            if((str[0]=='_')&&(str[1])==' ')
1921              str+=2;
1922            switch(format) {
1923            case cPLog_pml_lf:
1924              a =strlen(str);
1925              while(a) { /* trim CR/LF etc. */
1926                if(*(str+a)>=32) break;
1927                *(str+a)=0;
1928                a--;
1929              }
1930            case cPLog_pml:
1931              strcpy(buffer,"cmd.do('''");
1932              strcat(buffer,str);
1933              strcat(buffer,"''')\n");
1934              break;
1935            case cPLog_pym:
1936              strcpy(buffer,str);
1937              strcat(buffer,"\n");
1938              break;
1939            }
1940          }
1941          PyObject_CallMethod(log,"write","s",buffer);       
1942          PyObject_CallMethod(log,"flush","");
1943        }
1944      }
1945      PAutoUnblock(G,blocked);
1946    }
1947}
1948
1949void PLogFlush(PyMOLGlobals *G)
1950{
1951  int mode;
1952  PyObject *log;
1953  int blocked;
1954  mode = (int)SettingGet(G,cSetting_logging);
1955  if(mode)
1956    {
1957      blocked = PAutoBlock(G);
1958      log = PyDict_GetItemString(P_pymol_dict,P_log_file_str);
1959      if(log&&(log!=Py_None)) {
1960        PyObject_CallMethod(log,"flush","");
1961      }
1962      PAutoUnblock(G,blocked);
1963    }
1964}
1965
1966void PFlush(PyMOLGlobals *G) { 
1967  /* NOTE: ASSUMES unblocked Python threads and a locked API */
1968  PyObject *err;
1969  char buffer[OrthoLineLength+1];
1970  while(OrthoCommandOut(G,buffer)) {
1971    PBlockAndUnlockAPI(G);
1972   
1973    PXDecRef(PyObject_CallFunction(G->P_inst->parse,"si",buffer,0));
1974    err = PyErr_Occurred();
1975    if(err) {
1976      PyErr_Print();
1977      PRINTFB(G,FB_Python,FB_Errors)
1978        " PFlush: Uncaught exception.  PyMOL may have a bug.\n"
1979        ENDFB(G);
1980    }
1981    PLockAPIAndUnblock(G);
1982  }
1983}
1984
1985void PFlushFast(PyMOLGlobals *G) {
1986  /* NOTE: ASSUMES we currently have blocked Python threads and an unlocked API */
1987  PyObject *err;
1988  char buffer[OrthoLineLength+1];
1989  while(OrthoCommandOut(G,buffer)) {
1990    PRINTFD(G,FB_Threads)
1991      " PFlushFast-DEBUG: executing '%s' as thread 0x%x\n",buffer,
1992      PyThread_get_thread_ident()
1993      ENDFD;
1994    PXDecRef(PyObject_CallFunction(G->P_inst->parse,"si",buffer,0));
1995    err = PyErr_Occurred();
1996    if(err) {
1997      PyErr_Print();
1998      PRINTFB(G,FB_Python,FB_Errors)
1999        " PFlushFast: Uncaught exception.  PyMOL may have a bug.\n"
2000        ENDFB(G);
2001    }
2002  }
2003}
2004
2005
2006void PBlockLegacy()
2007{
2008  PBlock(TempPyMOLGlobals);
2009}
2010
2011void PUnblockLegacy()
2012{
2013  PUnblock(TempPyMOLGlobals);
2014}
2015
2016void PBlock(PyMOLGlobals *G)
2017{
2018
2019  if(!PAutoBlock(G)) {
2020    ErrFatal(G,"PBlock","Threading error detected.  Terminating...");
2021  }
2022}
2023
2024
2025int PAutoBlock(PyMOLGlobals *G)
2026{
2027#ifndef _PYMOL_ACTIVEX
2028#ifndef _PYMOL_EMBEDDED
2029  int a,id;
2030  /* synchronize python */
2031
2032  id = PyThread_get_thread_ident();
2033  PRINTFD(G,FB_Threads)
2034         " PAutoBlock-DEBUG: search 0x%x (0x%x, 0x%x, 0x%x)\n",id,
2035         SavedThread[MAX_SAVED_THREAD-1].id,
2036         SavedThread[MAX_SAVED_THREAD-2].id,
2037         SavedThread[MAX_SAVED_THREAD-3].id
2038         ENDFD;
2039  a = MAX_SAVED_THREAD-1;
2040  while(a) {
2041    if(!((SavedThread+a)->id-id)) {
2042      /* astoundingly, equality test fails on ALPHA even
2043       * though the ints are equal. Must be some kind of optimizer bug
2044       * or mis-assumption */
2045     
2046      PRINTFD(G,FB_Threads)
2047        " PAutoBlock-DEBUG: seeking global lock 0x%x\n",id
2048      ENDFD;
2049
2050#ifdef PYMOL_NEW_THREADS
2051
2052      PyEval_AcquireLock();
2053
2054      PRINTFD(G,FB_Threads)
2055        " PAutoBlock-DEBUG: restoring 0x%x\n",id
2056      ENDFD;
2057     
2058      PyThreadState_Swap((SavedThread+a)->state);
2059
2060#else
2061      PRINTFD(G,FB_Threads)
2062        " PAutoBlock-DEBUG: restoring 0x%x\n",id
2063      ENDFD;
2064     
2065      PyEval_RestoreThread((SavedThread+a)->state);
2066#endif
2067     
2068      PRINTFD(G,FB_Threads)
2069        " PAutoBlock-DEBUG: restored 0x%x\n",id
2070      ENDFD;
2071
2072      PRINTFD(G,FB_Threads)
2073        " PAutoBlock-DEBUG: clearing 0x%x\n",id
2074      ENDFD;
2075
2076      PXDecRef(PyObject_CallFunction(P_lock_c,NULL));
2077      SavedThread[a].id = -1;
2078      /* this is the only safe time we can change things */
2079      PXDecRef(PyObject_CallFunction(P_unlock_c,NULL));
2080     
2081      PRINTFD(G,FB_Threads)
2082        " PAutoBlock-DEBUG: blocked 0x%x (0x%x, 0x%x, 0x%x)\n",PyThread_get_thread_ident(),
2083        SavedThread[MAX_SAVED_THREAD-1].id,
2084        SavedThread[MAX_SAVED_THREAD-2].id,
2085        SavedThread[MAX_SAVED_THREAD-3].id
2086        ENDFD;
2087
2088      return 1;
2089    }
2090    a--;
2091  }
2092  PRINTFD(G,FB_Threads)
2093    " PAutoBlock-DEBUG: 0x%x not found, thus already blocked.\n",PyThread_get_thread_ident()
2094    ENDFD;
2095  return 0;
2096#else
2097  return 1;
2098#endif
2099#else
2100  return 1;
2101#endif
2102}
2103
2104int PIsGlutThread(void)
2105{
2106  return(PyThread_get_thread_ident()==P_glut_thread_id);
2107}
2108
2109void PUnblock(PyMOLGlobals *G)
2110{
2111#ifndef _PYMOL_ACTIVEX
2112#ifndef _PYMOL_EMBEDDED
2113  int a;
2114  /* NOTE: ASSUMES a locked API */
2115
2116  PRINTFD(G,FB_Threads)
2117    " PUnblock-DEBUG: entered as thread 0x%x\n",PyThread_get_thread_ident()
2118    ENDFD;
2119
2120  /* reserve a space while we have a lock */
2121  PXDecRef(PyObject_CallFunction(P_lock_c,NULL));
2122  a = MAX_SAVED_THREAD-1;
2123  while(a) {
2124    if((SavedThread+a)->id == -1 ) {
2125      (SavedThread+a)->id = PyThread_get_thread_ident();
2126#ifdef PYMOL_NEW_THREADS
2127      (SavedThread+a)->state = PyThreadState_Get();
2128#endif
2129      break;
2130    }
2131    a--;
2132  }
2133  PRINTFD(G,FB_Threads)
2134    " PUnblock-DEBUG: 0x%x stored in slot %d\n",(SavedThread+a)->id,a
2135    ENDFD;
2136  PXDecRef(PyObject_CallFunction(P_unlock_c,NULL));
2137#ifdef PYMOL_NEW_THREADS
2138  PyThreadState_Swap(NULL);
2139  PyEval_ReleaseLock();
2140#else
2141  (SavedThread+a)->state = PyEval_SaveThread(); 
2142#endif
2143 
2144#endif
2145#endif
2146
2147}
2148
2149
2150void PAutoUnblock(PyMOLGlobals *G,int flag)
2151{
2152  if(flag) PUnblock(G);
2153}
2154
2155void PBlockAndUnlockAPI(PyMOLGlobals *G)
2156{
2157  PBlock(G);
2158  PXDecRef(PyObject_CallFunction(P_unlock,NULL));
2159}
2160
2161void PLockAPIAndUnblock(PyMOLGlobals *G)
2162{
2163  PXDecRef(PyObject_CallFunction(P_lock,NULL));
2164  PUnblock(G);
2165}
2166
2167void PDefineFloat(PyMOLGlobals *G,char *name,float value) {
2168  char buffer[OrthoLineLength];
2169  sprintf(buffer,"%s = %f\n",name,value);
2170  PBlock(G);
2171  PRunStringModule(G,buffer);
2172  PUnblock(G);
2173}
2174
2175
2176/* This function is called by the interpreter to get its own name */
2177char *getprogramname(void)
2178{
2179        return("PyMOL");
2180}
2181
2182/* A static module */
2183
2184static PyObject *PCatchWrite(PyObject *self,    PyObject *args)
2185{
2186  char *str;
2187  PyArg_ParseTuple(args,"s",&str);
2188  if(str[0]) {
2189    if(TempPyMOLGlobals) {
2190      if(Feedback(TempPyMOLGlobals,FB_Python,FB_Output)) {
2191        OrthoAddOutput(TempPyMOLGlobals,str);
2192      }
2193    }
2194  }
2195  Py_INCREF(Py_None);
2196  return Py_None;
2197}
2198
2199static PyObject *PCatchFlush(PyObject *self,    PyObject *args)
2200{
2201  fflush(stdout);
2202  fflush(stderr);
2203  Py_INCREF(Py_None);
2204  return Py_None;
2205}
2206
2207static PyMethodDef PCatch_methods[] = {
2208        {"write",         PCatchWrite,   METH_VARARGS},
2209        {"flush",         PCatchFlush,   METH_VARARGS},
2210        {NULL,          NULL}           /* sentinel */
2211};
2212
2213void PCatchInit(void)
2214{
2215        PyImport_AddModule("pcatch");
2216        Py_InitModule("pcatch", PCatch_methods);
2217}
2218#else
2219typedef int this_source_file_is_not_empty;
2220#endif
2221
2222
Note: See TracBrowser for help on using the repository browser.