1
2 /*
3 A* -------------------------------------------------------------------
4 B* This file contains source code for the PyMOL computer program
5 C* Copyright (c) Schrodinger, LLC.
6 D* -------------------------------------------------------------------
7 E* It is unlawful to modify or remove this copyright notice.
8 F* -------------------------------------------------------------------
9 G* Please see the accompanying LICENSE file for further information.
10 H* -------------------------------------------------------------------
11 I* Additional authors of this source file include:
12 -*
13 -*
14 -*
15 Z* -------------------------------------------------------------------
16 */
17 #include"os_python.h"
18 #include "os_std.h"
19 #include "os_gl.h"
20
21 #include <clocale>
22
23 #include "MemoryDebug.h"
24
25 #include "Base.h"
26
27 #include "OVContext.h"
28
29 #include "MemoryDebug.h"
30 #include "Err.h"
31 #include "Util.h"
32 #include "Selector.h"
33 #include "Color.h"
34 #include "Ortho.h"
35 #include "Scene.h"
36 #include "PyMOLObject.h"
37 #include "Executive.h"
38 #include "Word.h"
39 #include "RepMesh.h"
40 #include "ObjectMolecule.h"
41 #include "Control.h"
42 #include "Sphere.h"
43 #include "Setting.h"
44 #include "Ray.h"
45 #include "Util.h"
46 #include "Movie.h"
47 #include "P.h"
48 #include "Editor.h"
49 #include "SculptCache.h"
50 #include "Isosurf.h"
51 #include "Tetsurf.h"
52 #include "PConv.h"
53 #include "VFont.h"
54 #include "Wizard.h"
55 #include "Text.h"
56 #include "Character.h"
57 #include "Seq.h"
58 #include "Seeker.h"
59 #include "Texture.h"
60 #include "TestPyMOL.h"
61 #include "TypeFace.h"
62 #include "PlugIOManager.h"
63 #include "MovieScene.h"
64 #include "Lex.h"
65 #include "SelectorDef.h"
66
67 #ifdef _PYMOL_OPENVR
68 #include "OpenVRMode.h"
69 #endif
70
71 #include "PyMOL.h"
72 #include "PyMOLGlobals.h"
73 #include "PyMOLOptions.h"
74 #include "Feedback.h"
75 #include "GraphicsUtil.h"
76 #include "pymol/zstring_view.h"
77
78 #include "ShaderMgr.h"
79 #include "Version.h"
80
81 #ifndef _PYMOL_NOPY
82 PyMOLGlobals *SingletonPyMOLGlobals = NULL;
83 #endif
84
85 #ifdef _PYMOL_LIB_HAS_PYTHON
86 #define PYMOL_API_LOCK if(I->PythonInitStage && (!I->ModalDraw)) { PLockAPIAndUnblock(I->G); {
87 #define PYMOL_API_LOCK_MODAL if(I->PythonInitStage) { PLockAPIAndUnblock(I->G); {
88 #define PYMOL_API_TRYLOCK if(I->PythonInitStage && (!I->ModalDraw)) { if(PTryLockAPIAndUnblock(I->G)) {
89 #define PYMOL_API_UNLOCK PBlockAndUnlockAPI(I->G); }}
90 #define PYMOL_API_UNLOCK_NO_FLUSH PBlockAndUnlockAPI(I->G); }}
91 #else
92 #define PYMOL_API_LOCK if(!I->ModalDraw) {
93 #define PYMOL_API_LOCK_MODAL {
94 #define PYMOL_API_TRYLOCK if(!I->ModalDraw) {
95 #define PYMOL_API_UNLOCK }
96 #define PYMOL_API_UNLOCK_NO_FLUSH }
97 #endif
98 #define IDLE_AND_READY 3
99
100 typedef struct _CPyMOL {
101 PyMOLGlobals *G;
102 int FakeDragFlag;
103 int RedisplayFlag;
104 int PassiveFlag;
105 int SwapFlag;
106 int BusyFlag;
107 int InterruptFlag;
108 int ReshapeFlag;
109 int ClickReadyFlag;
110 int DrawnFlag;
111 ObjectNameType ClickedObject;
112 int ClickedIndex, ClickedButton, ClickedModifiers, ClickedX, ClickedY, ClickedHavePos, ClickedPosState;
113 float ClickedPos[3];
114 int ImageRequestedFlag, ImageReadyFlag;
115 int DraggedFlag;
116 int Reshape[PYMOL_RESHAPE_SIZE];
117 int Progress[PYMOL_PROGRESS_SIZE];
118 int ProgressChanged;
119 int IdleAndReady;
120 int ExpireCount;
121 bool done_ConfigureShaders;
122
123 PyMOLModalDrawFn *ModalDraw;
124
125 PyMOLSwapBuffersFn *SwapFn;
126
127
128 /* Python stuff */
129 #ifndef _PYMOL_NOPY
130 int PythonInitStage;
131 #endif
132 /* dynamically mapped string constants */
133
134 OVLexicon *Lex;
135 OVOneToOne *Rep;
136 ov_word lex_everything, lex_sticks, lex_spheres, lex_surface;
137 ov_word lex_labels, lex_nb_spheres, lex_cartoon, lex_ribbon;
138 ov_word lex_lines, lex_mesh, lex_dots, lex_dashes, lex_nonbonded;
139 ov_word lex_cell, lex_cgo, lex_callback, lex_extent, lex_slice;
140
141 OVOneToOne *Clip;
142 ov_word lex_near, lex_far, lex_move, lex_slab, lex_atoms;
143
144 OVOneToOne *Reinit;
145 ov_word lex_settings;
146
147 OVOneToOne *SelectList;
148 ov_word lex_index, lex_id, lex_rank;
149
150 OVOneToOne *Setting;
151
152 #ifdef _PYMOL_LIB
153 OVOneToOne *MouseButtonCodeLexicon;
154 ov_word lex_left, lex_middle, lex_right;
155 ov_word lex_wheel;
156 ov_word lex_double_left, lex_double_middle, lex_double_right;
157 ov_word lex_single_left, lex_single_middle, lex_single_right;
158
159 OVOneToOne *MouseButtonModCodeLexicon;
160 ov_word lex_none, lex_shft, lex_ctrl, lex_ctsh;
161 ov_word lex_alt, lex_alsh, lex_ctal, lex_ctas;
162
163 OVOneToOne *MouseButtonActionCodeLexicon;
164 ov_word lex_but_rota, lex_but_move, lex_but_movz, lex_but_clip, lex_but_rotz;
165 ov_word lex_but_clpn, lex_but_clpf, lex_but_lb, lex_but_mb, lex_but_rb;
166 ov_word lex_but_plus_lb, lex_but_plus_mb, lex_but_plus_rb, lex_but_pkat, lex_but_pkbd;
167 ov_word lex_but_rotf, lex_but_torf, lex_but_movf, lex_but_orig, lex_but_plus_lbx;
168 ov_word lex_but_minus_lbx, lex_but_lbbx, lex_but_none, lex_but_cent, lex_but_pktb;
169 ov_word lex_but_slab, lex_but_movs, lex_but_pk1;
170 ov_word lex_but_mova, lex_but_menu, lex_but_sele, lex_but_plus_minus;
171 ov_word lex_but_plus_box, lex_but_minus_box, lex_but_mvsz, lex_but_dgrt, lex_but_dgmv;
172 ov_word lex_but_dgmz, lex_but_roto, lex_but_movo, lex_but_mvoz, lex_but_mvfz;
173 ov_word lex_but_mvaz, lex_but_drgm, lex_but_rotv, lex_but_movv, lex_but_mvvz;
174 ov_word lex_but_drgo, lex_but_imsz, lex_but_imvz, lex_but_box, lex_but_irtz;
175
176 OVOneToOne *MouseModeLexicon;
177 #include "buttonmodes_lex_def.h"
178
179 OVOneToOne *PaletteLexicon;
180 #include "palettes_lex_def.h"
181
182 #endif
183
184 AtomPropertyInfo AtomPropertyInfos[NUM_ATOM_PROPERTIES];
185 OVOneToOne *AtomPropertyLexicon;
186 ov_word lex_atom_prop_model, lex_atom_prop_index, lex_atom_prop_type,
187 lex_atom_prop_name, lex_atom_prop_resn, lex_atom_prop_resi,
188 lex_atom_prop_resv, lex_atom_prop_chain, lex_atom_prop_alt,
189 lex_atom_prop_segi, lex_atom_prop_elem,
190 lex_atom_prop_ss, lex_atom_prop_text_type,
191 lex_atom_prop_custom, lex_atom_prop_label, lex_atom_prop_numeric_type,
192 lex_atom_prop_q, lex_atom_prop_b, lex_atom_prop_vdw,
193 lex_atom_prop_elec_radius, lex_atom_prop_partial_charge, lex_atom_prop_formal_charge,
194 lex_atom_prop_stereo, lex_atom_prop_cartoon, lex_atom_prop_color,
195 lex_atom_prop_ID, lex_atom_prop_rank, lex_atom_prop_flags,
196 lex_atom_prop_geom, lex_atom_prop_valence,
197 lex_atom_prop_x, lex_atom_prop_y, lex_atom_prop_z,
198 lex_atom_prop_settings, lex_atom_prop_properties,
199 lex_atom_prop_reps,
200 lex_atom_prop_protons,
201 lex_atom_prop_oneletter,
202 lex_atom_prop_s, lex_atom_prop_p, lex_atom_prop_state;
203 /*
204 lex_atom_prop_, lex_atom_prop_, lex_atom_prop_,
205 lex_atom_prop_, lex_atom_prop_, lex_atom_prop_,*/
206
207 } _CPyMOL;
208
209
210 /* convenience functions -- inline */
211
get_status_ok(int ok)212 inline PyMOLstatus get_status_ok(int ok)
213 {
214 if(ok)
215 return PyMOLstatus_SUCCESS;
216 else
217 return PyMOLstatus_FAILURE;
218 }
219
return_status_ok(int ok)220 inline PyMOLreturn_status return_status_ok(int ok)
221 {
222 PyMOLreturn_status result;
223 result.status = get_status_ok(ok);
224 return result;
225 }
226
return_status(int status)227 inline PyMOLreturn_status return_status(int status)
228 {
229 PyMOLreturn_status result;
230 result.status = status;
231 return result;
232 }
233
return_result(const pymol::Result<float> & res)234 inline PyMOLreturn_float return_result(const pymol::Result<float>& res)
235 {
236 PyMOLreturn_float result = {PyMOLstatus_FAILURE};
237 if (res) {
238 result.status = PyMOLstatus_SUCCESS;
239 result.value = res.result();
240 }
241 return result;
242 }
243
return_result(const pymol::Result<std::vector<const char * >> & res)244 static PyMOLreturn_string_array return_result(
245 const pymol::Result<std::vector<const char*>>& res)
246 {
247 PyMOLreturn_string_array result = {
248 PyMOLstatus_SUCCESS, 0, nullptr};
249 if (!res) {
250 result.status = PyMOLstatus_FAILURE;
251 } else if (!res.result().empty()) {
252 const auto& vec = res.result();
253 result.size = vec.size();
254 result.array = VLAlloc(char*, result.size);
255
256 // allocate space for concatenated string in first array element
257 size_t reslen = 0;
258 for (const char* s : vec) {
259 reslen += strlen(s) + 1;
260 }
261 result.array[0] = VLAlloc(char, reslen);
262
263 // copy elements
264 for (size_t pl = 0, i = 0; i != vec.size(); ++i) {
265 result.array[i] = result.array[0] + pl;
266 strcpy(result.array[i], vec[i]);
267 pl += strlen(vec[i]) + 1;
268 }
269 }
270 return result;
271 }
272
273 #if defined(__cplusplus) && !defined(_WEBGL)
274 extern "C" {
275 #endif
276
277 #ifdef _PYMOL_LIB
278 int initial_button_modes[cButModeInputCount];
279 #endif
280
PyMOL_InitAPI(CPyMOL * I)281 static OVstatus PyMOL_InitAPI(CPyMOL * I)
282 {
283 OVContext *C = I->G->Context;
284 OVreturn_word result;
285 I->Lex = OVLexicon_New(C->heap);
286 if(!I->Lex)
287 return_OVstatus_FAILURE;
288
289 /* the following preprocessor macros may require GNU's cpp or VC++
290 we'll see... */
291
292 #define LEX(ARG) \
293 if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#ARG)))) \
294 return_OVstatus_FAILURE \
295 else \
296 I -> lex_ ## ARG = result.word;
297
298 /* string constants that are accepted on input */
299
300 #define LEX_REP(NAME,CODE) LEX(NAME) \
301 if(!OVreturn_IS_OK( OVOneToOne_Set(I->Rep,I->lex_ ## NAME, CODE))) \
302 return_OVstatus_FAILURE;
303
304 I->Rep = OVOneToOne_New(C->heap);
305 if(!I->Rep)
306 return_OVstatus_FAILURE;
307
308 LEX_REP(everything, -1);
309 LEX_REP(sticks, 0);
310 LEX_REP(spheres, 1);
311 LEX_REP(surface, 2);
312 LEX_REP(labels, 3);
313 LEX_REP(nb_spheres, 4);
314 LEX_REP(cartoon, 5);
315 LEX_REP(ribbon, 6);
316 LEX_REP(lines, 7);
317 LEX_REP(mesh, 8);
318 LEX_REP(dots, 9);
319 LEX_REP(dashes, 10);
320 LEX_REP(nonbonded, 11);
321 LEX_REP(cell, 12);
322 LEX_REP(cgo, 13);
323 LEX_REP(callback, 14);
324 LEX_REP(extent, 15);
325 LEX_REP(slice, 16);
326
327 /* workaround for unexplained bug with nested macro on VC6 */
328
329 #define LEX_CLIP(NAME,CODE) {if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#NAME)))) \
330 return_OVstatus_FAILURE \
331 else \
332 I -> lex_ ## NAME = result.word;} \
333 if(!OVreturn_IS_OK( OVOneToOne_Set(I->Clip,I->lex_ ## NAME, CODE))) \
334 return_OVstatus_FAILURE;
335
336 I->Clip = OVOneToOne_New(C->heap);
337 if(!I->Clip)
338 return_OVstatus_FAILURE;
339
340 LEX_CLIP(near, 0);
341 LEX_CLIP(far, 1);
342 LEX_CLIP(move, 2);
343 LEX_CLIP(slab, 3);
344 LEX_CLIP(atoms, 4);
345
346 #define LEX_REINIT(NAME,CODE) {if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#NAME)))) \
347 return_OVstatus_FAILURE \
348 else \
349 I -> lex_ ## NAME = result.word;} \
350 if(!OVreturn_IS_OK( OVOneToOne_Set(I->Reinit,I->lex_ ## NAME, CODE))) \
351 return_OVstatus_FAILURE;
352
353 I->Reinit = OVOneToOne_New(C->heap);
354 if(!I->Reinit)
355 return_OVstatus_FAILURE;
356
357 LEX_REINIT(everything, 0);
358 LEX_REINIT(settings, 1);
359
360 #define LEX_SELLIST(NAME,CODE) {if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#NAME)))) \
361 return_OVstatus_FAILURE \
362 else \
363 I -> lex_ ## NAME = result.word;} \
364 if(!OVreturn_IS_OK( OVOneToOne_Set(I->SelectList,I->lex_ ## NAME, CODE))) \
365 return_OVstatus_FAILURE;
366
367 I->SelectList = OVOneToOne_New(C->heap);
368 if(!I->SelectList)
369 return_OVstatus_FAILURE;
370
371 LEX_SELLIST(index, 0);
372 LEX_SELLIST(id, 1);
373 LEX_SELLIST(rank, 2);
374
375 I->Setting = OVOneToOne_New(C->heap);
376 if(!I->Setting)
377 return_OVstatus_FAILURE;
378
379 if(!CPyMOLInitSetting(I->Lex, I->Setting))
380 return_OVstatus_FAILURE;
381
382 #ifdef _PYMOL_LIB
383
384 I->MouseButtonCodeLexicon = OVOneToOne_New(C->heap);
385 if(!I->MouseButtonCodeLexicon)
386 return_OVstatus_FAILURE;
387
388 #define LEX_MOUSECODE(NAME,CODE) LEX(NAME) \
389 if(!OVreturn_IS_OK( OVOneToOne_Set(I->MouseButtonCodeLexicon,I->lex_ ## NAME, CODE))) \
390 return_OVstatus_FAILURE;
391
392 LEX_MOUSECODE(left, 0);
393 LEX_MOUSECODE(middle, 1);
394 LEX_MOUSECODE(right, 2);
395 LEX_MOUSECODE(wheel, 3);
396 LEX_MOUSECODE(double_left, 4);
397 LEX_MOUSECODE(double_middle, 5);
398 LEX_MOUSECODE(double_right, 6);
399 LEX_MOUSECODE(single_left, 7);
400 LEX_MOUSECODE(single_middle, 8);
401 LEX_MOUSECODE(single_right, 9);
402
403 I->MouseButtonModCodeLexicon = OVOneToOne_New(C->heap);
404 if(!I->MouseButtonModCodeLexicon)
405 return_OVstatus_FAILURE;
406
407 #define LEX_BUTTONMODCODE(NAME,CODE) LEX(NAME) \
408 if(!OVreturn_IS_OK( OVOneToOne_Set(I->MouseButtonModCodeLexicon,I->lex_ ## NAME, CODE))) \
409 return_OVstatus_FAILURE;
410
411 LEX_BUTTONMODCODE(none, 0);
412 LEX_BUTTONMODCODE(shft, 1);
413 LEX_BUTTONMODCODE(ctrl, 2);
414 LEX_BUTTONMODCODE(ctsh, 3);
415 LEX_BUTTONMODCODE(alt, 4);
416 LEX_BUTTONMODCODE(alsh, 5);
417 LEX_BUTTONMODCODE(ctal, 6);
418 LEX_BUTTONMODCODE(ctas, 7);
419
420 I->MouseButtonActionCodeLexicon = OVOneToOne_New(C->heap);
421 if(!I->MouseButtonActionCodeLexicon)
422 return_OVstatus_FAILURE;
423
424 #define LEX_BUT(ARG) \
425 if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#ARG)))) \
426 return_OVstatus_FAILURE \
427 else \
428 I -> lex_but_ ## ARG = result.word;
429
430 #define LEX_BUTTONACTIONCODE(NAME,CODE) LEX_BUT(NAME) \
431 if(!OVreturn_IS_OK( OVOneToOne_Set(I->MouseButtonActionCodeLexicon,I->lex_but_ ## NAME, CODE))) \
432 return_OVstatus_FAILURE;
433 #define LEX_BUTTONACTIONCODEWITHSTRING(NAME,STRARG,CODE) \
434 if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,STRARG)))) \
435 return_OVstatus_FAILURE \
436 else \
437 I -> lex_but_ ## NAME = result.word; \
438 if(!OVreturn_IS_OK( OVOneToOne_Set(I->MouseButtonActionCodeLexicon,I->lex_but_ ## NAME, CODE))) \
439 return_OVstatus_FAILURE;
440
441
442 LEX_BUTTONACTIONCODE(rota, 0);
443 LEX_BUTTONACTIONCODE(move, 1);
444 LEX_BUTTONACTIONCODE(movz, 2);
445 LEX_BUTTONACTIONCODE(clip, 3);
446 LEX_BUTTONACTIONCODE(rotz, 4);
447 LEX_BUTTONACTIONCODE(clpn, 5);
448 LEX_BUTTONACTIONCODE(clpf, 6);
449 LEX_BUTTONACTIONCODE(lb, 7);
450 LEX_BUTTONACTIONCODE(mb, 8);
451 LEX_BUTTONACTIONCODE(rb, 9);
452 LEX_BUTTONACTIONCODEWITHSTRING(plus_lb, "+lb", 10);
453 LEX_BUTTONACTIONCODEWITHSTRING(plus_mb, "+mb", 11);
454 LEX_BUTTONACTIONCODEWITHSTRING(plus_rb, "+rb", 12);
455 LEX_BUTTONACTIONCODE(pkat, 13);
456 LEX_BUTTONACTIONCODE(pkbd, 14);
457 LEX_BUTTONACTIONCODE(rotf, 15);
458 LEX_BUTTONACTIONCODE(torf, 16);
459 LEX_BUTTONACTIONCODE(movf, 17);
460 LEX_BUTTONACTIONCODE(orig, 18);
461 LEX_BUTTONACTIONCODEWITHSTRING(plus_lbx, "+lbx", 19);
462 LEX_BUTTONACTIONCODEWITHSTRING(minus_lbx, "-lbx", 20);
463 LEX_BUTTONACTIONCODE(lbbx, 21);
464 LEX_BUTTONACTIONCODE(none, 22);
465 LEX_BUTTONACTIONCODE(cent, 23);
466 LEX_BUTTONACTIONCODE(pktb, 24);
467 LEX_BUTTONACTIONCODE(slab, 25);
468 LEX_BUTTONACTIONCODE(movs, 26);
469 LEX_BUTTONACTIONCODE(pk1, 27);
470 LEX_BUTTONACTIONCODE(mova, 28);
471 LEX_BUTTONACTIONCODE(menu, 29);
472 LEX_BUTTONACTIONCODE(sele, 30);
473 LEX_BUTTONACTIONCODEWITHSTRING(plus_minus,"+/-", 31);
474 LEX_BUTTONACTIONCODEWITHSTRING(plus_box, "+box", 32);
475 LEX_BUTTONACTIONCODEWITHSTRING(minus_box, "-box", 33);
476 LEX_BUTTONACTIONCODE(mvsz, 34);
477 LEX_BUTTONACTIONCODE(dgrt, 36);
478 LEX_BUTTONACTIONCODE(dgmv, 37);
479 LEX_BUTTONACTIONCODE(dgmz, 38);
480 LEX_BUTTONACTIONCODE(roto, 39);
481 LEX_BUTTONACTIONCODE(movo, 40);
482 LEX_BUTTONACTIONCODE(mvoz, 41);
483 LEX_BUTTONACTIONCODE(mvfz, 42);
484 LEX_BUTTONACTIONCODE(mvaz, 43);
485 LEX_BUTTONACTIONCODE(drgm, 44);
486 LEX_BUTTONACTIONCODE(rotv, 45);
487 LEX_BUTTONACTIONCODE(movv, 46);
488 LEX_BUTTONACTIONCODE(mvvz, 47);
489 LEX_BUTTONACTIONCODE(drgo, 49);
490 LEX_BUTTONACTIONCODE(imsz, 50);
491 LEX_BUTTONACTIONCODE(imvz, 51);
492 LEX_BUTTONACTIONCODE(box, 52);
493 LEX_BUTTONACTIONCODE(irtz, 53);
494
495 I->MouseModeLexicon = OVOneToOne_New(C->heap);
496 if(!I->MouseModeLexicon)
497 return_OVstatus_FAILURE;
498
499 #define LEX_MOUSEMODECODE(NAME,CODE) LEX(NAME) \
500 if(!OVreturn_IS_OK( OVOneToOne_Set(I->MouseModeLexicon,I->lex_ ## NAME, CODE))) \
501 return_OVstatus_FAILURE;
502
503 #include "buttonmodes_lex_init.h"
504
505 {
506 int a;
507 /* These are set by default for the modes, basically, any single or double
508 click is a simple click (i.e., cButModeSimpleClick), mouse button
509 actions are initialized to a potential click, wheel actions are set to none.
510 This is very similar to what is done in PyMOL_SetMouseButtonMode(),
511 and it makes it easier to specify new modes without needing to set
512 every mouse function */
513 for(a = cButModeLeftDouble /* 16 */; a <= cButModeRightCtrlAltShftSingle /* 63 */; a++) {
514 /* all single and double clicks */
515 initial_button_modes[a] = cButModeSimpleClick;
516 }
517 for(a = cButModeLeftAlt /* 68 */; a <= cButModeRightCtrlAltShft /* 79 */; a++) {
518 /* all button modes with Alt */
519 initial_button_modes[a] = cButModePotentialClick;
520 }
521 for(a = cButModeLeftNone /* 0 */; a <= cButModeRightCtSh /* 11 */; a++) {
522 /* all button modes without Alt */
523 initial_button_modes[a] = cButModePotentialClick;
524 }
525 for(a = cButModeWheelNone /* 12 */; a <= cButModeWheelCtSh /* 15 */; a++) {
526 initial_button_modes[a] = cButModeNone;
527 }
528 for(a = cButModeWheelAlt /* 64 */; a <= cButModeWheelCtrlAltShft /* 67 */; a++) {
529 initial_button_modes[a] = cButModeNone;
530 }
531 }
532
533 I->PaletteLexicon = OVOneToOne_New(C->heap);
534 if(!I->PaletteLexicon)
535 return_OVstatus_FAILURE;
536
537 #define LEX_PALETTE(NAME,CODE) LEX(NAME) \
538 if(!OVreturn_IS_OK( OVOneToOne_Set(I->PaletteLexicon,I->lex_ ## NAME, CODE))) \
539 return_OVstatus_FAILURE;
540
541 #include "palettes_lex_init.h"
542
543 #endif
544
545
546 I->AtomPropertyLexicon = OVOneToOne_New(C->heap);
547 if(!I->AtomPropertyLexicon)
548 return_OVstatus_FAILURE;
549
550 #define LEX_ATM_PROP(ARG) \
551 if(!OVreturn_IS_OK( (result= OVLexicon_GetFromCString(I->Lex,#ARG)))) \
552 return_OVstatus_FAILURE \
553 else \
554 I -> lex_atom_prop_ ## ARG = result.word;
555 #define LEX_ATOM_PROP(NAME,CODE,TYPE,OFFSET) LEX_ATM_PROP(NAME) \
556 if(!OVreturn_IS_OK( OVOneToOne_Set(I->AtomPropertyLexicon,I->lex_atom_prop_ ## NAME, CODE))) \
557 return_OVstatus_FAILURE; \
558 I->AtomPropertyInfos[CODE].id = CODE; \
559 I->AtomPropertyInfos[CODE].Ptype = TYPE; \
560 I->AtomPropertyInfos[CODE].offset = OFFSET; \
561 I->AtomPropertyInfos[CODE].maxlen = 0;
562
563 #define LEX_ATOM_PROP_S(NAME,CODE,TYPE,OFFSET,MAXLEN) LEX_ATM_PROP(NAME) \
564 if(!OVreturn_IS_OK( OVOneToOne_Set(I->AtomPropertyLexicon,I->lex_atom_prop_ ## NAME, CODE))) \
565 return_OVstatus_FAILURE; \
566 I->AtomPropertyInfos[CODE].id = CODE; \
567 I->AtomPropertyInfos[CODE].Ptype = TYPE; \
568 I->AtomPropertyInfos[CODE].offset = OFFSET; \
569 I->AtomPropertyInfos[CODE].maxlen = MAXLEN;
570
571 /*TEMP*/
572 LEX_ATOM_PROP(model, 0, cPType_model, 0);
573 LEX_ATOM_PROP(index, 1, cPType_index, 0);
574 LEX_ATOM_PROP(type, 2, cPType_char_as_type, 0);
575 LEX_ATOM_PROP(name, 3, cPType_int_as_string, offsetof(AtomInfoType,name));
576 LEX_ATOM_PROP(resn, 4, cPType_int_as_string, offsetof(AtomInfoType,resn));
577 LEX_ATOM_PROP(resi, 5, 0, 0);
578 LEX_ATOM_PROP(resv, 6, cPType_int, offsetof(AtomInfoType,resv));
579 LEX_ATOM_PROP(chain, 7, cPType_int_as_string, offsetof(AtomInfoType,chain));
580 LEX_ATOM_PROP_S(alt, 8, cPType_string, offsetof(AtomInfoType,alt), 1);
581 LEX_ATOM_PROP(segi, 9, cPType_int_as_string, offsetof(AtomInfoType,segi));
582 LEX_ATOM_PROP_S(elem, 10, cPType_string, offsetof(AtomInfoType,elem), cElemNameLen);
583 LEX_ATOM_PROP_S(ss, 11, cPType_string, offsetof(AtomInfoType,ssType), 1);
584 LEX_ATOM_PROP(text_type, 12, cPType_int_as_string, offsetof(AtomInfoType,textType));
585 LEX_ATOM_PROP(custom, 13, cPType_int_as_string, offsetof(AtomInfoType,custom));
586 LEX_ATOM_PROP(label, 14, cPType_int_as_string, offsetof(AtomInfoType,label));
587 LEX_ATOM_PROP(numeric_type, 15, cPType_int_custom_type, offsetof(AtomInfoType,customType));
588 LEX_ATOM_PROP(q, 16, cPType_float, offsetof(AtomInfoType,q));
589 LEX_ATOM_PROP(b, 17, cPType_float, offsetof(AtomInfoType,b));
590 LEX_ATOM_PROP(vdw, 18, cPType_float, offsetof(AtomInfoType,vdw));
591 LEX_ATOM_PROP(elec_radius, 19, cPType_float, offsetof(AtomInfoType,elec_radius));
592 LEX_ATOM_PROP(partial_charge, 20, cPType_float, offsetof(AtomInfoType,partialCharge));
593 LEX_ATOM_PROP(formal_charge, 21, cPType_schar, offsetof(AtomInfoType,formalCharge));
594 LEX_ATOM_PROP(stereo, 22, 0, 0);
595 LEX_ATOM_PROP(cartoon, 23, cPType_schar, offsetof(AtomInfoType,cartoon));
596 LEX_ATOM_PROP(color, 24, cPType_int, offsetof(AtomInfoType,color));
597 LEX_ATOM_PROP(ID, 25, cPType_int, offsetof(AtomInfoType,id));
598 LEX_ATOM_PROP(rank, 26, cPType_int, offsetof(AtomInfoType,rank));
599 LEX_ATOM_PROP(flags, 27, cPType_int, offsetof(AtomInfoType,flags));
600 LEX_ATOM_PROP(geom, 28, cPType_schar, offsetof(AtomInfoType,geom));
601 LEX_ATOM_PROP(valence, 29, cPType_schar, offsetof(AtomInfoType,valence));
602 LEX_ATOM_PROP(x, 30, cPType_xyz_float, 0);
603 LEX_ATOM_PROP(y, 31, cPType_xyz_float, 1);
604 LEX_ATOM_PROP(z, 32, cPType_xyz_float, 2);
605 LEX_ATOM_PROP(settings, 33, cPType_settings, 0);
606 LEX_ATOM_PROP(properties, 34, cPType_properties, 0);
607 LEX_ATOM_PROP(s, 35, cPType_settings, 0);
608 LEX_ATOM_PROP(p, 36, cPType_properties, 0);
609 LEX_ATOM_PROP(state, 37, cPType_state, 0);
610 LEX_ATOM_PROP(reps, 38, cPType_int, offsetof(AtomInfoType, visRep));
611 LEX_ATOM_PROP(protons, 39, cPType_schar, offsetof(AtomInfoType, protons));
612 LEX_ATOM_PROP(oneletter, 40, 0, 0);
613 // LEX_ATOM_PROP(, );
614
615 return_OVstatus_SUCCESS;
616 }
617
PyMOL_NewG3DStream(CPyMOL * I,int ** array_ptr)618 int PyMOL_NewG3DStream(CPyMOL * I, int **array_ptr)
619 {
620 int *return_vla = ExecutiveGetG3d(I->G);
621 int result = OVstatus_FAILURE;
622 if(return_vla) {
623 result = VLAGetSize(return_vla) * (sizeof(G3dPrimitive) / sizeof(int));
624 }
625 if(array_ptr)
626 *array_ptr = return_vla;
627 return result;
628 }
629
PyMOL_DelG3DStream(CPyMOL * I,int * array_ptr)630 int PyMOL_DelG3DStream(CPyMOL * I, int *array_ptr)
631 {
632 VLAFreeP(array_ptr);
633 return OVstatus_SUCCESS;
634 }
635
PyMOL_PurgeAPI(CPyMOL * I)636 static OVstatus PyMOL_PurgeAPI(CPyMOL * I)
637 {
638 OVOneToOne_DEL_AUTO_NULL(I->Setting);
639 OVOneToOne_DEL_AUTO_NULL(I->Clip);
640 OVOneToOne_DEL_AUTO_NULL(I->SelectList);
641 OVOneToOne_DEL_AUTO_NULL(I->Reinit);
642 OVOneToOne_DEL_AUTO_NULL(I->Rep);
643 #ifdef _PYMOL_LIB
644 OVOneToOne_DEL_AUTO_NULL(I->MouseButtonCodeLexicon);
645 OVOneToOne_DEL_AUTO_NULL(I->MouseButtonModCodeLexicon);
646 OVOneToOne_DEL_AUTO_NULL(I->MouseButtonActionCodeLexicon);
647 OVOneToOne_DEL_AUTO_NULL(I->MouseModeLexicon);
648 OVOneToOne_DEL_AUTO_NULL(I->PaletteLexicon);
649 OVOneToOne_DEL_AUTO_NULL(I->CartoonLexicon);
650 OVOneToOne_DEL_AUTO_NULL(I->FlagLexicon);
651 OVOneToOne_DEL_AUTO_NULL(I->FlagActionLexicon);
652 #endif
653
654 OVOneToOne_DEL_AUTO_NULL(I->AtomPropertyLexicon);
655
656 OVLexicon_DEL_AUTO_NULL(I->Lex);
657 return_OVstatus_SUCCESS;
658 }
659
PyMOL_FreeResultArray(CPyMOL * I,void * array)660 int PyMOL_FreeResultArray(CPyMOL * I, void *array)
661 {
662 if(array) {
663 VLAFreeP(array);
664 return PyMOLstatus_SUCCESS;
665 } else {
666 return PyMOLstatus_FAILURE;
667 }
668 }
669
PyMOL_CmdDraw(CPyMOL * I,int width,int height,int antialias,int quiet)670 PyMOLreturn_status PyMOL_CmdDraw(CPyMOL * I, int width, int height,
671 int antialias, int quiet)
672 {
673 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
674 PYMOL_API_LOCK
675 result.status =
676 get_status_ok(ExecutiveDrawCmd(I->G, width, height, antialias, false, quiet));
677 I->ImageRequestedFlag = true;
678 I->ImageReadyFlag = false;
679 PYMOL_API_UNLOCK return result;
680 }
681
PyMOL_CmdCapture(CPyMOL * I,int quiet)682 PyMOLreturn_status PyMOL_CmdCapture(CPyMOL * I, int quiet)
683 {
684 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
685 PYMOL_API_LOCK
686 result.status = get_status_ok(ExecutiveDrawCmd(I->G, -1, -1, 0, true, quiet));
687 I->ImageRequestedFlag = true;
688 I->ImageReadyFlag = false;
689 PYMOL_API_UNLOCK return result;
690 }
691
PyMOL_CmdRay(CPyMOL * I,int width,int height,int antialias,float angle,float shift,int renderer,int defer,int quiet)692 PyMOLreturn_status PyMOL_CmdRay(CPyMOL * I, int width, int height, int antialias,
693 float angle, float shift, int renderer, int defer,
694 int quiet)
695 {
696 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
697 PYMOL_API_LOCK if(renderer < 0)
698 renderer = SettingGetGlobal_i(I->G, cSetting_ray_default_renderer);
699 SceneInvalidateCopy(I->G, true);
700 result.status =
701 get_status_ok(ExecutiveRay
702 (I->G, width, height, renderer, angle, shift, quiet, defer, antialias));
703 if(defer) {
704 I->ImageRequestedFlag = true;
705 I->ImageReadyFlag = false;
706 } else {
707 I->ImageRequestedFlag = false;
708 if(SceneHasImage(I->G)) {
709 I->ImageReadyFlag = true;
710 } else {
711 I->ImageReadyFlag = false;
712 }
713 }
714 PYMOL_API_UNLOCK return result;
715 }
716
PyMOL_CmdSetView(CPyMOL * I,float * view,int view_len,float animate,int quiet)717 PyMOLreturn_status PyMOL_CmdSetView(CPyMOL * I, float *view, int view_len,
718 float animate, int quiet)
719 {
720 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
721 SceneViewType tmp;
722 PYMOL_API_LOCK if(view_len >= 18) {
723 int a;
724 UtilZeroMem(tmp, sizeof(tmp));
725 tmp[15] = 1.0F;
726 for(a = 0; a < 3; a++) {
727 tmp[a] = view[a];
728 tmp[a + 4] = view[a + 3];
729 tmp[a + 8] = view[a + 6];
730 tmp[a + 16] = view[a + 9];
731 tmp[a + 19] = view[a + 12];
732 tmp[a + 22] = view[a + 15];
733 }
734 SceneSetView(I->G, tmp, quiet, animate, 0); /* TO DO -- add hand to the API */
735 result.status = get_status_ok(true);
736 } else {
737 result.status = get_status_ok(false);
738 }
739 PYMOL_API_UNLOCK return result;
740 }
741
PyMOL_CmdGetView(CPyMOL * I,int quiet)742 PyMOLreturn_float_array PyMOL_CmdGetView(CPyMOL * I, int quiet)
743 {
744 PyMOLreturn_float_array result = { PyMOLstatus_FAILURE };
745 SceneViewType tmp;
746 PYMOL_API_LOCK result.size = 18;
747 result.array = VLAlloc(float, result.size);
748 if(result.array) {
749 int a;
750 SceneGetView(I->G, tmp);
751 for(a = 0; a < 3; a++) {
752 result.array[a] = tmp[a];
753 result.array[a + 3] = tmp[a + 4];
754 result.array[a + 6] = tmp[a + 8];
755 result.array[a + 9] = tmp[a + 16];
756 result.array[a + 12] = tmp[a + 19];
757 result.array[a + 15] = tmp[a + 22];
758 }
759 result.status = get_status_ok(true);
760 } else {
761 result.status = get_status_ok(false);
762 }
763 PYMOL_API_UNLOCK return result;
764 }
765
766
PyMOL_CmdAlign(CPyMOL * I,const char * source,const char * target,float cutoff,int cycles,float gap,float extend,int max_gap,const char * object,const char * matrix,int source_state,int target_state,int quiet,int max_skip,int transform,int reset)767 PyMOLreturn_float_array PyMOL_CmdAlign(CPyMOL * I, const char *source, const char *target,
768 float cutoff, int cycles, float gap, float extend,
769 int max_gap, const char *object, const char *matrix,
770 int source_state, int target_state, int quiet,
771 int max_skip, int transform, int reset)
772 {
773 PyMOLreturn_float_array result = { PyMOLstatus_FAILURE };
774 PYMOL_API_LOCK OrthoLineType s2 = "", s3 = "";
775 int ok = false;
776 ExecutiveRMSInfo rms_info;
777 result.size = 7;
778 result.array = VLAlloc(float, result.size);
779 if(!result.array) {
780 ok = false;
781 } else {
782 ok = ((SelectorGetTmp(I->G, source, s2) >= 0) &&
783 (SelectorGetTmp(I->G, target, s3) >= 0));
784 if(ok) {
785 const float _0 = 0.0F; /* GCC compiler bug workaround */
786 const float _m1 = -1.0F;
787 ok = ExecutiveAlign(I->G, s2, s3, matrix, gap, extend, max_gap,
788 max_skip, cutoff, cycles, quiet, object,
789 source_state - 1, target_state - 1,
790 &rms_info, transform, reset, _m1, _0, _0, _0, _0, _0, 0, _0);
791 if(ok) {
792 result.array[0] = rms_info.final_rms;
793 result.array[1] = rms_info.final_n_atom;
794 result.array[2] = rms_info.n_cycles_run;
795 result.array[3] = rms_info.initial_rms;
796 result.array[4] = rms_info.initial_n_atom;
797 result.array[5] = rms_info.raw_alignment_score;
798 result.array[6] = rms_info.n_residues_aligned;
799 }
800 }
801 }
802 SelectorFreeTmp(I->G, s2);
803 SelectorFreeTmp(I->G, s3);
804 if(!ok) {
805 VLAFreeP(result.array);
806 }
807 result.status = get_status_ok(ok);
808
809 PYMOL_API_UNLOCK return result;
810
811 }
812
PyMOL_CmdDelete(CPyMOL * I,const char * name,int quiet)813 PyMOLreturn_status PyMOL_CmdDelete(CPyMOL * I, const char *name, int quiet)
814 {
815 PYMOL_API_LOCK ExecutiveDelete(I->G, name);
816 PyMOL_NeedRedisplay(I); /* this should really only get called if ExecutiveDelete deletes something */
817 PYMOL_API_UNLOCK return return_status_ok(true); /* TO DO: return a real result */
818 }
819
PyMOL_CmdZoom(CPyMOL * I,const char * selection,float buffer,int state,int complete,float animate,int quiet)820 PyMOLreturn_status PyMOL_CmdZoom(CPyMOL * I, const char *selection, float buffer,
821 int state, int complete, float animate, int quiet)
822 {
823 int ok = false;
824 PYMOL_API_LOCK
825 auto result = ExecutiveWindowZoom(I->G, selection, buffer, state - 1,
826 complete, animate, quiet);
827 ok = static_cast<bool>(result);
828 PYMOL_API_UNLOCK return return_status_ok(ok);
829 }
830
PyMOL_CmdOrient(CPyMOL * I,const char * selection,float buffer,int state,int complete,float animate,int quiet)831 PyMOLreturn_status PyMOL_CmdOrient(CPyMOL * I, const char *selection, float buffer,
832 int state, int complete, float animate, int quiet)
833 {
834 int ok = true;
835 PYMOL_API_LOCK
836 auto res = ExecutiveOrient(
837 I->G, selection, state - 1, animate, complete, buffer, quiet);
838 ok = static_cast<bool>(res);
839 PYMOL_API_UNLOCK return return_status_ok(ok);
840 }
841
PyMOL_CmdCenter(CPyMOL * I,const char * selection,int state,int origin,float animate,int quiet)842 PyMOLreturn_status PyMOL_CmdCenter(CPyMOL * I, const char *selection, int state, int origin,
843 float animate, int quiet)
844 {
845 int ok = false;
846 PYMOL_API_LOCK
847 auto result = ExecutiveCenter(I->G, selection,
848 state - 1, origin, animate, nullptr, quiet);
849 ok = static_cast<bool>(result);
850 PYMOL_API_UNLOCK return return_status_ok(ok);
851 }
852
PyMOL_CmdOrigin(CPyMOL * I,const char * selection,int state,int quiet)853 PyMOLreturn_status PyMOL_CmdOrigin(CPyMOL * I, const char *selection, int state, int quiet)
854 {
855 int ok = true;
856 PYMOL_API_LOCK
857 float v[3] = { 0.0F, 0.0F, 0.0F };
858 auto result = ExecutiveOrigin(I->G, selection, true, "", v, state - 1);
859 ok = static_cast<bool>(result);
860 PYMOL_API_UNLOCK return return_status_ok(ok);
861 }
862
PyMOL_CmdOriginAt(CPyMOL * I,float x,float y,float z,int quiet)863 PyMOLreturn_status PyMOL_CmdOriginAt(CPyMOL * I, float x, float y, float z, int quiet)
864 {
865 int ok = true;
866 PYMOL_API_LOCK float v[3];
867 v[0] = x;
868 v[1] = y;
869 v[2] = z;
870 auto result = ExecutiveOrigin(I->G, "", true, "", v, 0);
871 ok = static_cast<bool>(ok);
872 PYMOL_API_UNLOCK return return_status_ok(ok);
873 }
874
get_rep_id(CPyMOL * I,const char * representation)875 static OVreturn_word get_rep_id(CPyMOL * I, const char *representation)
876 {
877 OVreturn_word result;
878
879 if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, representation))))
880 return result;
881 return OVOneToOne_GetForward(I->Rep, result.word);
882 }
883
get_setting_id(CPyMOL * I,const char * setting)884 OVreturn_word get_setting_id(CPyMOL * I, const char *setting)
885 {
886 OVreturn_word result;
887 if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, setting))))
888 return result;
889 return OVOneToOne_GetForward(I->Setting, result.word);
890 }
891
get_reinit_id(CPyMOL * I,const char * reinit)892 static OVreturn_word get_reinit_id(CPyMOL * I, const char *reinit)
893 {
894 OVreturn_word result;
895 if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, reinit))))
896 return result;
897 return OVOneToOne_GetForward(I->Reinit, result.word);
898 }
899
get_select_list_mode(CPyMOL * I,const char * mode)900 static OVreturn_word get_select_list_mode(CPyMOL * I, const char *mode)
901 {
902 OVreturn_word result;
903 if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, mode))))
904 return result;
905 return OVOneToOne_GetForward(I->SelectList, result.word);
906 }
907
PyMOL_CmdClip(CPyMOL * I,const char * mode,float amount,const char * selection,int state,int quiet)908 PyMOLreturn_status PyMOL_CmdClip(CPyMOL * I,
909 const char *mode, float amount,
910 const char *selection,
911 int state, int quiet)
912 {
913 int ok = true;
914 PYMOL_API_LOCK
915 cSceneClip clip_id = SceneClipGetEnum(mode);
916 SelectorTmp2 s1(I->G, selection);
917 SceneClip(I->G, clip_id, amount, s1.getName(), state - 1);
918 PYMOL_API_UNLOCK return return_status_ok(ok);
919 }
920
PyMOL_CmdLabel(CPyMOL * I,const char * selection,const char * text,int quiet)921 PyMOLreturn_status PyMOL_CmdLabel(CPyMOL * I, const char *selection, const char *text, int quiet)
922 {
923 int ok = true;
924 PYMOL_API_LOCK
925 auto result = ExecutiveLabel(I->G, selection, text, quiet, cExecutiveLabelEvalAlt);
926 ok = static_cast<bool>(result);
927 PYMOL_API_UNLOCK return return_status_ok(ok);
928 }
929
PyMOL_CmdSelect(CPyMOL * I,const char * name,const char * selection,int quiet)930 PyMOLreturn_status PyMOL_CmdSelect(CPyMOL * I, const char *name, const char *selection, int quiet)
931 {
932 int ret = -1;
933 PYMOL_API_LOCK
934
935 auto res = SelectorCreate(I->G, name, selection, NULL, quiet, NULL);
936 ret = res ? res.result() : -1;
937
938 PYMOL_API_UNLOCK return return_status_ok(ret >= 0); // if ret is negative it should fail
939 }
940
PyMOL_CmdSelectList(CPyMOL * I,const char * name,const char * object,int * list,int list_len,int state,const char * mode,int quiet)941 PyMOLreturn_status PyMOL_CmdSelectList(CPyMOL * I, const char *name, const char *object, int *list,
942 int list_len, int state, const char *mode, int quiet)
943 {
944 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
945 PYMOL_API_LOCK OVreturn_word mode_id;
946 if(OVreturn_IS_OK((mode_id = get_select_list_mode(I, mode)))) {
947 result.status =
948 ExecutiveSelectList(I->G, name, object, list, list_len, state - 1, mode_id.word,
949 quiet);
950 }
951 PYMOL_API_UNLOCK return result;
952 }
953
PyMOL_CmdShow(CPyMOL * I,const char * representation,const char * selection,int quiet)954 PyMOLreturn_status PyMOL_CmdShow(CPyMOL * I,
955 const char *representation,
956 const char *selection,
957 int quiet)
958 {
959 int ok = true;
960 PYMOL_API_LOCK OrthoLineType s1;
961 OVreturn_word rep_id;
962 if(OVreturn_IS_OK((rep_id = get_rep_id(I, representation)))) {
963 SelectorGetTmp2(I->G, selection, s1);
964 if (!s1[0]){ /* This doesn't catch patterns that don't match, but everything else */
965 ok = false;
966 } else {
967 ExecutiveSetRepVisib(I->G, s1, rep_id.word, true);
968 PyMOL_NeedRedisplay(I); /* this should really only get called if ExecutiveSetRepVisib changes something */
969 SelectorFreeTmp(I->G, s1);
970 }
971 } else {
972 ok = false;
973 }
974 PYMOL_API_UNLOCK return return_status_ok(ok);
975 }
976
PyMOL_CmdHide(CPyMOL * I,const char * representation,const char * selection,int quiet)977 PyMOLreturn_status PyMOL_CmdHide(CPyMOL * I,
978 const char *representation,
979 const char *selection,
980 int quiet)
981 {
982 int ok = true;
983 PYMOL_API_LOCK OrthoLineType s1;
984 OVreturn_word rep_id;
985 if(OVreturn_IS_OK((rep_id = get_rep_id(I, representation)))) {
986 SelectorGetTmp2(I->G, selection, s1);
987 if (!s1[0]){ /* This doesn't catch patterns that don't match, but everything else */
988 ok = false;
989 } else {
990 ExecutiveSetRepVisib(I->G, s1, rep_id.word, false);
991 SelectorFreeTmp(I->G, s1);
992 }
993 } else {
994 ok = false;
995 }
996 PYMOL_API_UNLOCK return return_status_ok(ok);
997 }
998
PyMOL_CmdEnable(CPyMOL * I,const char * name,int quiet)999 PyMOLreturn_status PyMOL_CmdEnable(CPyMOL * I, const char *name, int quiet)
1000 {
1001 int ok = false;
1002 PYMOL_API_LOCK if(name[0] == '(') {
1003 auto result1 = ExecutiveSetOnOffBySele(I->G, name, true);
1004 ok = static_cast<bool>(ok);
1005 }
1006 auto result2 = ExecutiveSetObjVisib(I->G, name, true, false); /* TO DO: parents */
1007 ok = static_cast<bool>(result2);
1008 PYMOL_API_UNLOCK return return_status_ok(ok);
1009 }
1010
PyMOL_CmdDisable(CPyMOL * I,const char * name,int quiet)1011 PyMOLreturn_status PyMOL_CmdDisable(CPyMOL * I, const char *name, int quiet)
1012 {
1013 int ok = false;
1014 PYMOL_API_LOCK if(name[0] == '(') {
1015 auto result = ExecutiveSetOnOffBySele(I->G, name, true);
1016 ok = static_cast<bool>(result);
1017 } else {
1018 auto result = ExecutiveSetObjVisib(I->G, name, false, false);
1019 ok = static_cast<bool>(result);
1020 }
1021 PYMOL_API_UNLOCK return return_status_ok(ok);
1022 }
1023
PyMOL_CmdSetBond(CPyMOL * I,const char * setting,const char * value,const char * selection1,const char * selection2,int state,int quiet,int side_effects)1024 PyMOLreturn_status PyMOL_CmdSetBond(CPyMOL * I, const char *setting, const char *value,
1025 const char *selection1, const char *selection2,
1026 int state, int quiet, int side_effects)
1027 {
1028 int ok = true;
1029 PYMOL_API_LOCK {
1030 OVreturn_word setting_id;
1031 OrthoLineType s1 = "";
1032 OrthoLineType s2 = "";
1033 if(ok) ok = OVreturn_IS_OK((setting_id = get_setting_id(I, setting)));
1034 if(ok) ok = (SelectorGetTmp(I->G, selection1, s1) >= 0);
1035 if(ok) {
1036 if(selection2 && selection2[0]) {
1037 ok = (SelectorGetTmp(I->G, selection2, s2) >= 0);
1038 } else {
1039 ok = (SelectorGetTmp(I->G, selection1, s2) >= 0);
1040 }
1041 }
1042 if(ok) {
1043 ok = ExecutiveSetBondSettingFromString(I->G, setting_id.word, value,
1044 s1, s2,
1045 state - 1, quiet, side_effects);
1046 }
1047 SelectorFreeTmp(I->G, s1);
1048 SelectorFreeTmp(I->G, s2);
1049 } PYMOL_API_UNLOCK
1050 return return_status_ok(ok);
1051 }
1052
PyMOL_CmdUnsetBond(CPyMOL * I,const char * setting,const char * selection1,const char * selection2,int state,int quiet,int side_effects)1053 PyMOLreturn_status PyMOL_CmdUnsetBond(CPyMOL * I, const char *setting,
1054 const char *selection1, const char *selection2,
1055 int state, int quiet, int side_effects)
1056 {
1057 int ok = true;
1058 PYMOL_API_LOCK {
1059 OVreturn_word setting_id;
1060 OrthoLineType s1 = "";
1061 OrthoLineType s2 = "";
1062 if(ok) ok = OVreturn_IS_OK((setting_id = get_setting_id(I, setting)));
1063 if(ok) ok = (SelectorGetTmp(I->G, selection1, s1) >= 0);
1064 if(ok) {
1065 if(selection2 && selection2[0]) {
1066 ok = (SelectorGetTmp(I->G, selection2, s2) >= 0);
1067 } else {
1068 ok = (SelectorGetTmp(I->G, selection1, s2) >= 0);
1069 }
1070 }
1071 if(ok) {
1072 ok = ExecutiveUnsetBondSetting(I->G, setting_id.word,
1073 s1, s2,
1074 state - 1, quiet, side_effects);
1075 }
1076 SelectorFreeTmp(I->G, s1);
1077 SelectorFreeTmp(I->G, s2);
1078 } PYMOL_API_UNLOCK
1079 return return_status_ok(ok);
1080 }
1081
PyMOL_CmdSet(CPyMOL * I,const char * setting,const char * value,const char * selection,int state,int quiet,int side_effects)1082 PyMOLreturn_status PyMOL_CmdSet(CPyMOL * I,
1083 const char *setting,
1084 const char *value,
1085 const char *selection,
1086 int state, int quiet, int side_effects)
1087 {
1088 int ok = true;
1089 PYMOL_API_LOCK {
1090 OVreturn_word setting_id;
1091 OrthoLineType s1 = "";
1092 if(ok) ok = OVreturn_IS_OK((setting_id = get_setting_id(I, setting)));
1093 if(ok) ok = (SelectorGetTmp2(I->G, selection, s1) >= 0);
1094
1095 if(ok) {
1096 ExecutiveSetSettingFromString(I->G, setting_id.word, value, s1,
1097 state - 1, quiet, side_effects);
1098 }
1099 SelectorFreeTmp(I->G, s1);
1100 }
1101 PYMOL_API_UNLOCK return return_status_ok(ok);
1102 }
1103
PyMOL_CmdGet(CPyMOL * I,const char * setting,const char * selection,int state,int quiet)1104 PyMOLreturn_value PyMOL_CmdGet(CPyMOL * I,
1105 const char *setting,
1106 const char *selection,
1107 int state, int quiet){
1108 int ok = true;
1109 PyMOLreturn_value result = { PyMOLstatus_SUCCESS };
1110
1111 PYMOL_API_LOCK {
1112 OVreturn_word setting_id;
1113 OrthoLineType s1 = "";
1114 if(ok) ok = OVreturn_IS_OK((setting_id = get_setting_id(I, setting)));
1115 if(ok) ok = (SelectorGetTmp2(I->G, selection, s1) >= 0);
1116
1117 if(ok) {
1118 ExecutiveGetSettingFromString(I->G, &result, setting_id.word, s1,
1119 state - 1, quiet);
1120 }
1121 SelectorFreeTmp(I->G, s1);
1122 }
1123 PYMOL_API_UNLOCK return result;
1124 }
1125
1126
PyMOL_CmdUnset(CPyMOL * I,const char * setting,const char * selection,int state,int quiet,int side_effects)1127 PyMOLreturn_status PyMOL_CmdUnset(CPyMOL * I, const char *setting, const char *selection,
1128 int state, int quiet, int side_effects)
1129 {
1130 int ok = true;
1131 PYMOL_API_LOCK {
1132 OVreturn_word setting_id;
1133 OrthoLineType s1 = "";
1134 if(ok) ok = OVreturn_IS_OK((setting_id = get_setting_id(I, setting)));
1135 if(ok) ok = (SelectorGetTmp2(I->G, selection, s1) >= 0);
1136 if(ok) {
1137 ExecutiveUnsetSetting(I->G, setting_id.word, s1,
1138 state - 1, quiet, side_effects);
1139 }
1140 SelectorFreeTmp(I->G, s1);
1141 }
1142 PYMOL_API_UNLOCK return return_status_ok(ok);
1143 }
1144
PyMOL_CmdColor(CPyMOL * I,const char * color,const char * selection,int flags,int quiet)1145 PyMOLreturn_status PyMOL_CmdColor(CPyMOL * I, const char *color, const char *selection, int flags,
1146 int quiet)
1147 {
1148 int ok = true;
1149 PYMOL_API_LOCK
1150 auto result = ExecutiveColor(I->G, selection, color, flags, quiet);
1151 ok = static_cast<bool>(result);
1152 PYMOL_API_UNLOCK return return_status_ok(ok);
1153 }
1154
1155 /* -- JV */
PyMOL_CmdBackgroundColor(CPyMOL * I,const char * value)1156 PyMOLreturn_status PyMOL_CmdBackgroundColor(CPyMOL * I, const char *value) {
1157 int ok = true;
1158 PYMOL_API_LOCK
1159
1160 int idx = ColorGetIndex(I->G, value);
1161 if(idx >= 0){
1162 SettingSetGlobal_i(I->G, cSetting_bg_rgb, idx);
1163 } else {
1164 ErrMessage(I->G, "Color", "Bad color name.");
1165 }
1166 PYMOL_API_UNLOCK return return_status_ok(ok);
1167 }
1168
PyMOL_CmdReinitialize(CPyMOL * I,const char * what,const char * object_name)1169 PyMOLreturn_status PyMOL_CmdReinitialize(CPyMOL * I,
1170 const char *what,
1171 const char *object_name)
1172 {
1173 int ok = true;
1174 OVreturn_word what_id;
1175 PYMOL_API_LOCK if(OVreturn_IS_OK((what_id = get_reinit_id(I, what)))) {
1176 auto res = ExecutiveReinitialize(I->G, what_id.word, object_name);
1177 ok = static_cast<bool>(res);
1178 }
1179 PYMOL_API_UNLOCK return return_status_ok(ok);
1180 }
1181
PyMOL_CmdGetMovieLength(CPyMOL * I,int quiet)1182 PyMOLreturn_int PyMOL_CmdGetMovieLength(CPyMOL * I,int quiet)
1183 {
1184 int ok = true;
1185 PyMOLreturn_int result;
1186 result.status = PyMOLstatus_FAILURE;
1187 result.value = 0;
1188
1189 PYMOL_API_LOCK
1190 if(ok) {
1191 result.value = MovieGetLength(I->G);
1192 result.status = get_status_ok(ok);
1193 };
1194 PYMOL_API_UNLOCK return result;
1195 }
1196
PyMOL_CmdGetDistance(CPyMOL * I,const char * selection1,const char * selection2,int state,int quiet)1197 PyMOLreturn_float PyMOL_CmdGetDistance(CPyMOL * I,
1198 const char *selection1,
1199 const char *selection2, int state, int quiet)
1200 {
1201 PyMOLreturn_float result;
1202 PYMOL_API_LOCK {
1203 result = return_result(ExecutiveGetDistance(I->G,
1204 selection1,
1205 selection2,
1206 state));
1207 }
1208 PYMOL_API_UNLOCK return result;
1209 }
1210
PyMOL_CmdDistance(CPyMOL * I,const char * name,const char * selection1,const char * selection2,int mode,float cutoff,int label,int reset,int zoom,int state,int quiet)1211 PyMOLreturn_float PyMOL_CmdDistance(CPyMOL * I,
1212 const char *name,
1213 const char *selection1,
1214 const char *selection2,
1215 int mode,
1216 float cutoff,
1217 int label, int reset, int zoom, int state, int quiet)
1218 {
1219 PyMOLreturn_float result;
1220 PYMOL_API_LOCK {
1221 int defState1 = -4, defState2 = -4;
1222 auto res = ExecutiveDistance(I->G, name,
1223 selection1, selection2, mode, cutoff, label, quiet, reset, state, zoom, defState1, defState2);
1224 result = return_result(res);
1225 }
1226 PYMOL_API_UNLOCK return result;
1227 }
1228
PyMOL_CmdGetAngle(CPyMOL * I,const char * selection1,const char * selection2,const char * selection3,int state,int quiet)1229 PyMOLreturn_float PyMOL_CmdGetAngle(CPyMOL * I,
1230 const char *selection1,
1231 const char *selection2,
1232 const char *selection3, int state, int quiet)
1233 {
1234 PyMOLreturn_float result;
1235 PYMOL_API_LOCK {
1236 result = return_result(ExecutiveGetAngle(I->G,
1237 selection1,
1238 selection2,
1239 selection3,
1240 state));
1241 }
1242 PYMOL_API_UNLOCK return result;
1243 }
1244
PyMOL_CmdAngle(CPyMOL * I,const char * name,const char * selection1,const char * selection2,const char * selection3,int mode,int label,int reset,int zoom,int state,int quiet)1245 PyMOLreturn_float PyMOL_CmdAngle(CPyMOL * I,
1246 const char *name,
1247 const char *selection1,
1248 const char *selection2,
1249 const char *selection3,
1250 int mode,
1251 int label, int reset, int zoom, int state, int quiet)
1252 {
1253 PyMOLreturn_float result;
1254 PYMOL_API_LOCK {
1255 int defState1 = -4, defState2 = -4, defState3 = -3;
1256 auto res = ExecutiveAngle(I->G, name,
1257 selection1, selection2, selection3, mode, label, reset, zoom, quiet,
1258 state, defState1, defState2, defState3);
1259 result = return_result(res);
1260 }
1261 PYMOL_API_UNLOCK return result;
1262 }
1263
PyMOL_CmdGetDihedral(CPyMOL * I,const char * selection1,const char * selection2,const char * selection3,const char * selection4,int state,int quiet)1264 PyMOLreturn_float PyMOL_CmdGetDihedral(CPyMOL * I,
1265 const char *selection1,
1266 const char *selection2,
1267 const char *selection3,
1268 const char *selection4, int state, int quiet)
1269 {
1270 PyMOLreturn_float result;
1271 PYMOL_API_LOCK {
1272 result = return_result(ExecutiveGetDihe(I->G,
1273 selection1,
1274 selection2,
1275 selection3,
1276 selection4,
1277 state));
1278 }
1279 PYMOL_API_UNLOCK return result;
1280 }
1281
PyMOL_CmdDihedral(CPyMOL * I,const char * name,const char * selection1,const char * selection2,const char * selection3,const char * selection4,int mode,int label,int reset,int zoom,int state,int quiet)1282 PyMOLreturn_float PyMOL_CmdDihedral(CPyMOL * I,
1283 const char *name,
1284 const char *selection1,
1285 const char *selection2,
1286 const char *selection3,
1287 const char *selection4,
1288 int mode,
1289 int label, int reset, int zoom, int state, int quiet)
1290 {
1291 PyMOLreturn_float result;
1292 PYMOL_API_LOCK {
1293 auto res = ExecutiveDihedral(I->G,
1294 name, selection1, selection2, selection3, selection4, mode, label,
1295 reset, zoom, quiet, state);
1296 result = return_result(res);
1297 }
1298 PYMOL_API_UNLOCK return result;
1299 }
1300
PyMOL_CmdIsodot(CPyMOL * I,const char * name,const char * map_name,float level,const char * selection,float buffer,int state,float carve,int source_state,int quiet)1301 PyMOLreturn_status PyMOL_CmdIsodot(CPyMOL * I, const char *name, const char *map_name, float level,
1302 const char *selection, float buffer, int state, float carve,
1303 int source_state, int quiet)
1304 {
1305 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
1306 PYMOL_API_LOCK
1307 auto res = ExecutiveIsomeshEtc(I->G, name, map_name, level, selection, buffer,
1308 state - 1, carve, source_state - 1, quiet, 1, level);
1309 result.status = get_status_ok(bool(res));
1310 PYMOL_API_UNLOCK return result;
1311
1312 }
1313
PyMOL_CmdIsomesh(CPyMOL * I,const char * name,const char * map_name,float level,const char * selection,float buffer,int state,float carve,int source_state,int quiet)1314 PyMOLreturn_status PyMOL_CmdIsomesh(CPyMOL * I, const char *name, const char *map_name, float level,
1315 const char *selection, float buffer, int state, float carve,
1316 int source_state, int quiet)
1317 {
1318 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
1319 PYMOL_API_LOCK
1320 auto res = ExecutiveIsomeshEtc(I->G, name, map_name, level, selection, buffer,
1321 state - 1, carve, source_state - 1, quiet, 0, level);
1322 result.status = get_status_ok(bool(res));
1323 PYMOL_API_UNLOCK return result;
1324 }
1325
PyMOL_CmdIsosurface(CPyMOL * I,const char * name,const char * map_name,float level,const char * selection,float buffer,int state,float carve,int source_state,int side,int mode,int quiet)1326 PyMOLreturn_status PyMOL_CmdIsosurface(CPyMOL * I, const char *name, const char *map_name,
1327 float level, const char *selection, float buffer,
1328 int state, float carve, int source_state, int side,
1329 int mode, int quiet)
1330 {
1331 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
1332 PYMOL_API_LOCK
1333 auto res = ExecutiveIsosurfaceEtc(I->G, name, map_name, level, selection,
1334 buffer, state - 1, carve, source_state - 1, side, quiet, mode);
1335 result.status = get_status_ok(bool(res));
1336 PYMOL_API_UNLOCK return result;
1337 }
1338
PyMOL_CmdGradient(CPyMOL * I,const char * name,const char * map_name,float minimum,float maximum,const char * selection,float buffer,int state,float carve,int source_state,int quiet)1339 PyMOLreturn_status PyMOL_CmdGradient(CPyMOL * I, const char *name, const char *map_name,
1340 float minimum, float maximum, const char *selection,
1341 float buffer, int state, float carve,
1342 int source_state, int quiet)
1343 {
1344 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
1345 PYMOL_API_LOCK
1346 auto res = ExecutiveIsomeshEtc(I->G, name, map_name, minimum, selection,
1347 buffer, state - 1, carve, source_state - 1, quiet, 3, maximum);
1348 result.status = get_status_ok(bool(res));
1349 PYMOL_API_UNLOCK return result;
1350 }
1351
PyMOL_CmdIsolevel(CPyMOL * I,const char * name,float level,int state,int query,int quiet)1352 PyMOLreturn_float PyMOL_CmdIsolevel(CPyMOL * I, const char *name, float level, int state,
1353 int query, int quiet)
1354 {
1355 PyMOLreturn_float result;
1356 PYMOL_API_LOCK
1357 if(query) {
1358 auto res = ExecutiveGetIsolevel(I->G, name, state - 1);
1359 result = return_result(res);
1360 } else {
1361 auto res = ExecutiveIsolevel(I->G, name, level, state - 1, quiet);
1362 result.status = get_status_ok(static_cast<bool>(res));
1363 result.value = level;
1364 }
1365 PYMOL_API_UNLOCK return result;
1366 }
1367
word_count(const char * src)1368 static int word_count(const char *src)
1369 { /* only works for ascii */
1370 int cnt = 0;
1371 while((*src) && ((*src) < 33)) /* skip leading whitespace */
1372 src++;
1373 while(*src) {
1374 if((*src) > 32) {
1375 cnt++;
1376 while((*src) && ((*src) > 32))
1377 src++;
1378 }
1379 while((*src) && ((*src) < 33))
1380 src++;
1381 }
1382 return cnt;
1383 }
1384
next_word(const char * src,char * dst,int buf_size)1385 static const char *next_word(const char *src, char *dst, int buf_size)
1386 { /* only works for ascii */
1387 while((*src) && ((*src) < 33)) /* skip leading whitespace */
1388 src++;
1389 while(*src) {
1390 if((*src) > 32) {
1391 while((*src) && ((*src) > 32) && (buf_size > 1)) {
1392 *(dst++) = *(src++);
1393 buf_size--;
1394 }
1395 break;
1396 }
1397 }
1398 dst[0] = 0;
1399 return src;
1400 }
1401
PyMOL_CmdRampNew(CPyMOL * I,const char * name,const char * map,float * range,int n_level,const char * color,int state,const char * selection,float beyond,float within,float sigma,int zero,int calc_mode,int quiet)1402 PyMOLreturn_status PyMOL_CmdRampNew(CPyMOL * I, const char *name, const char *map, float *range,
1403 int n_level, const char *color, int state, const char *selection,
1404 float beyond, float within, float sigma,
1405 int zero, int calc_mode, int quiet)
1406 {
1407 int ok = true;
1408 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
1409 OrthoLineType s1 = "";
1410 float *color_vla = NULL;
1411 float *range_vla = NULL;
1412 PYMOL_API_LOCK if(selection && selection[0]) {
1413 if(ok)
1414 ok = (SelectorGetTmp(I->G, selection, s1) >= 0);
1415 }
1416 if(ok) {
1417 if(range && n_level) {
1418 range_vla = VLAlloc(float, n_level);
1419 UtilCopyMem(range_vla, range, sizeof(float) * n_level);
1420 }
1421 }
1422
1423 if(ok && color) {
1424 int n_color = word_count(color);
1425 /* to do */
1426 if(color && n_color) {
1427 color_vla = VLAlloc(float, n_color * 3);
1428 if(color_vla) {
1429 WordType colorName;
1430 int a;
1431 for(a = 0; a < n_color; a++) {
1432 color = next_word(color, colorName, sizeof(colorName));
1433 {
1434 const float *src = ColorGetNamed(I->G, colorName);
1435 float *dst = color_vla + 3 * a;
1436 copy3f(src, dst);
1437 }
1438 }
1439 }
1440 }
1441 }
1442 if(ok) {
1443 auto res =
1444 ExecutiveRampNew(I->G, name, map, pymol::vla_take_ownership(range_vla),
1445 pymol::vla_take_ownership(color_vla), state, s1, beyond, within,
1446 sigma, zero, calc_mode, quiet);
1447 ok = static_cast<bool>(res);
1448 result.status = get_status_ok(ok);
1449 } else {
1450 result.status = PyMOLstatus_FAILURE;
1451 }
1452 SelectorFreeTmp(I->G, s1);
1453 PYMOL_API_UNLOCK return result;
1454 }
1455
1456 /*
1457 * Supported file formats and they internal codes
1458 */
1459 struct {
1460 const char * name;
1461 cLoadType_t code_buffer;
1462 cLoadType_t code_filename;
1463 } const ContentTypeTable[] = {
1464 // molecules
1465 {"pdb", cLoadTypePDBStr, cLoadTypePDB},
1466 {"vdb", cLoadTypeVDBStr, cLoadTypeUnknown},
1467 {"cif", cLoadTypeCIFStr, cLoadTypeCIF},
1468 {"mmtf", cLoadTypeMMTFStr, cLoadTypeMMTF},
1469 {"mae", cLoadTypeMAEStr, cLoadTypeMAE},
1470 {"sdf", cLoadTypeSDF2Str, cLoadTypeSDF2},
1471 {"mol", cLoadTypeMOLStr, cLoadTypeMOL},
1472 {"mol2", cLoadTypeMOL2Str, cLoadTypeMOL2},
1473 {"xyz", cLoadTypeXYZStr, cLoadTypeXYZ},
1474 {"pqr", cLoadTypeUnknown, cLoadTypePQR},
1475 {"macromodel", cLoadTypeMMDStr, cLoadTypeMMD},
1476 // maps
1477 {"ccp4", cLoadTypeCCP4Str, cLoadTypeUnknown},
1478 {"xplor", cLoadTypeXPLORStr, cLoadTypeXPLORMap},
1479 {"phi", cLoadTypePHIStr, cLoadTypePHIMap},
1480 {"dx", cLoadTypeUnknown, cLoadTypeDXMap},
1481 // special
1482 {"cgo", cLoadTypeCGO, cLoadTypeUnknown},
1483 {NULL, cLoadTypeUnknown, cLoadTypeUnknown}
1484 };
1485
1486 /*
1487 * Proxy for "ExecutiveLoad" with string "content_format" (and "content_type")
1488 * argument.
1489 *
1490 * content: Either file name or file contents, depending on "content_type"
1491 * content_type: "filename", "string", "raw", or "cgo"
1492 * content_length: Length of "content", if it's not a file name or a
1493 * null-terminated string (pass -1).
1494 * content_format: The file format, e.g. "pdb", "sdf", "mol2", ...
1495 * object_name: New object name. Can be empty if "content_type" is
1496 * "filename".
1497 */
Loader(CPyMOL * I,const char * content,const char * content_type,int content_length,const char * content_format,const char * object_name,int state,int discrete,int finish,int quiet,int multiplex,int zoom)1498 static PyMOLreturn_status Loader(CPyMOL * I, const char *content, const char *content_type,
1499 int content_length, const char *content_format,
1500 const char *object_name, int state,
1501 int discrete, int finish,
1502 int quiet, int multiplex, int zoom)
1503 {
1504 PyMOLGlobals * G = I->G;
1505 bool content_is_filename = false;
1506 int ok = true;
1507 WordType obj_name;
1508
1509 // `content` can be a file name, or the file contents
1510 if (strcmp(content_type, "filename") == 0) {
1511 content_is_filename = true;
1512 } else if (strcmp(content_type, "string") == 0) {
1513 if (content_length < 0)
1514 content_length = strlen(content);
1515 } else if (
1516 strcmp(content_type, "raw") != 0 &&
1517 strcmp(content_type, "cgo") != 0) {
1518 PRINTFB(G, FB_Executive, FB_Errors)
1519 " Error: Unknown content type '%s'\n", content_type ENDFB(G);
1520 ok = false;
1521 }
1522
1523 if(ok) {
1524 { /* if object_name is blank and content is a filename, then
1525 compute the object_name from the file prefix */
1526 if((!object_name[0]) && content_is_filename) {
1527 const char *start, *stop;
1528 stop = start = content + strlen(content) - 1;
1529 while(start > content) { /* known path separators */
1530 if((start[-1] == ':') || (start[-1] == '\'') || (start[-1] == '/'))
1531 break;
1532 start--;
1533 }
1534 while(stop > start) {
1535 if(*stop == '.')
1536 break;
1537 stop--;
1538 }
1539 if(stop == start)
1540 stop = content + strlen(content);
1541 if((stop - start) >= sizeof(WordType))
1542 stop = start + sizeof(WordType) - 1;
1543 {
1544 char *q;
1545 const char *p = start;
1546 q = obj_name;
1547 while(p < stop) {
1548 *(q++) = *(p++);
1549 }
1550 *q = 0;
1551 object_name = obj_name;
1552 }
1553 }
1554 }
1555 {
1556 cLoadType_t pymol_content_type = cLoadTypeUnknown;
1557
1558 for (auto it = ContentTypeTable; it->name; ++it) {
1559 if (strcmp(it->name, content_format) == 0) {
1560 pymol_content_type = content_is_filename ?
1561 it->code_filename : it->code_buffer;
1562 break;
1563 }
1564 }
1565
1566 if (pymol_content_type == cLoadTypeUnknown) {
1567 PRINTFB(G, FB_Executive, FB_Errors)
1568 " Error: Unknown content format '%s' with type '%s'\n",
1569 content_format, content_type ENDFB(G);
1570 ok = false;
1571 }
1572
1573 if(ok) {
1574 auto result = ExecutiveLoad(I->G,
1575 content_is_filename ? content : nullptr,
1576 content_is_filename ? nullptr : content,
1577 content_length,
1578 pymol_content_type,
1579 object_name,
1580 state - 1, zoom, discrete, finish, multiplex, quiet, NULL, 0, NULL);
1581 ok = static_cast<bool>(result);
1582 }
1583 }
1584 }
1585 if (ok)
1586 PyMOL_NeedRedisplay(I);
1587 return return_status_ok(ok);
1588 }
1589
PyMOL_CmdLoad(CPyMOL * I,const char * content,const char * content_type,const char * content_format,const char * object_name,int state,int discrete,int finish,int quiet,int multiplex,int zoom)1590 PyMOLreturn_status PyMOL_CmdLoad(CPyMOL * I,
1591 const char *content,
1592 const char *content_type,
1593 const char *content_format,
1594 const char *object_name, int state,
1595 int discrete, int finish,
1596 int quiet, int multiplex, int zoom)
1597 {
1598 PyMOLreturn_status status = { PyMOLstatus_FAILURE };
1599 PYMOL_API_LOCK
1600 status = Loader(I, content, content_type, -1, content_format, object_name,
1601 state, discrete, finish, quiet, multiplex, zoom);
1602 PYMOL_API_UNLOCK return status;
1603 }
1604
PyMOL_CmdLoadRaw(CPyMOL * I,const char * content,int content_length,const char * content_format,const char * object_name,int state,int discrete,int finish,int quiet,int multiplex,int zoom)1605 PyMOLreturn_status PyMOL_CmdLoadRaw(CPyMOL * I,
1606 const char *content,
1607 int content_length,
1608 const char *content_format,
1609 const char *object_name, int state,
1610 int discrete, int finish,
1611 int quiet, int multiplex, int zoom)
1612 {
1613 PyMOLreturn_status status = { PyMOLstatus_FAILURE };
1614 PYMOL_API_LOCK
1615 status = Loader(I, content, "raw", content_length, content_format,
1616 object_name, state, discrete, finish, quiet, multiplex, zoom);
1617 PYMOL_API_UNLOCK return status;
1618 }
1619
PyMOL_CmdLoadCGO(CPyMOL * I,const float * content,int content_length,const char * object_name,int state,int quiet,int zoom)1620 PyMOLreturn_status PyMOL_CmdLoadCGO(CPyMOL * I,
1621 const float *content,
1622 int content_length,
1623 const char *object_name, int state, int quiet, int zoom)
1624 {
1625 PyMOLreturn_status status = { PyMOLstatus_FAILURE };
1626 PYMOL_API_LOCK
1627 status = Loader(I, (char *) content, "cgo", content_length, "cgo",
1628 object_name, state, 0, 1, quiet, 0, zoom);
1629 PYMOL_API_UNLOCK return status;
1630 }
1631
PyMOL_CmdCreate(CPyMOL * I,const char * name,const char * selection,int source_state,int target_state,int discrete,int zoom,int quiet,int singletons,const char * extract,int copy_properties)1632 PyMOLreturn_status PyMOL_CmdCreate(CPyMOL * I,
1633 const char *name,
1634 const char *selection, int source_state,
1635 int target_state, int discrete,
1636 int zoom, int quiet, int singletons,
1637 const char *extract, int copy_properties)
1638 {
1639 int ok = true;
1640 PYMOL_API_LOCK
1641 auto result = ExecutiveSeleToObject(I->G,
1642 name, selection, source_state, target_state, discrete, zoom, quiet,
1643 singletons, copy_properties);
1644 ok = static_cast<bool>(result);
1645 PYMOL_API_UNLOCK return return_status_ok(ok);
1646 }
1647
PyMOL_CmdPseudoatom(CPyMOL * I,const char * object_name,const char * selection,const char * name,const char * resn,const char * resi,const char * chain,const char * segi,const char * elem,float vdw,int hetatm,float b,float q,const char * color,const char * label,int use_xyz,float x,float y,float z,int state,int mode,int quiet)1648 PyMOLreturn_status PyMOL_CmdPseudoatom(CPyMOL * I, const char *object_name, const char *selection,
1649 const char *name, const char *resn, const char *resi, const char *chain,
1650 const char *segi, const char *elem, float vdw, int hetatm,
1651 float b, float q, const char *color, const char *label,
1652 int use_xyz, float x, float y, float z,
1653 int state, int mode, int quiet)
1654 {
1655 int ok = true;
1656 PYMOL_API_LOCK
1657 if(ok) {
1658 int color_index = ColorGetIndex(I->G, color);
1659 if(ok) {
1660 float pos_tmp[3], *pos = pos_tmp;
1661 if(use_xyz) {
1662 pos[0] = x;
1663 pos[1] = y;
1664 pos[2] = z;
1665 } else {
1666 pos = NULL;
1667 }
1668 auto pseudoatom_name = ExecutivePreparePseudoatomName(I->G, object_name);
1669 auto res = ExecutivePseudoatom(I->G, pseudoatom_name, selection, name,
1670 resn, resi, chain, segi, elem, vdw, hetatm, b, q, label, pos,
1671 color_index, state - 1, mode, quiet);
1672 ok = static_cast<bool>(res);
1673 }
1674 }
1675 PYMOL_API_UNLOCK return return_status_ok(ok);
1676 }
1677
PyMOL_CmdTurn(CPyMOL * I,char axis,float angle)1678 PyMOLreturn_status PyMOL_CmdTurn(CPyMOL * I, char axis, float angle){
1679 PyMOLreturn_status result = { PyMOLstatus_SUCCESS };
1680 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
1681 switch (axis){
1682 case 'x':
1683 SceneRotate(G, angle, 1.0, 0.0, 0.0);
1684 break;
1685 case 'y':
1686 SceneRotate(G, angle, 0.0, 1.0, 0.0);
1687 break;
1688 case 'z':
1689 SceneRotate(G, angle, 0.0, 0.0, 1.0);
1690 break;
1691 default:
1692 result.status = PyMOLstatus_FAILURE;
1693 break;
1694 }
1695 PYMOL_API_UNLOCK return result;
1696 }
1697
PyMOL_CmdMPlay(CPyMOL * I,int cmd)1698 PyMOLreturn_status PyMOL_CmdMPlay(CPyMOL * I, int cmd){
1699 PyMOLreturn_status result = { PyMOLstatus_SUCCESS };
1700 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
1701 MoviePlay(G, cmd);
1702 PYMOL_API_UNLOCK return result;
1703 }
1704
PyMOL_CmdSetFeedbackMask(CPyMOL * I,int action,int module,int mask)1705 PyMOLreturn_status PyMOL_CmdSetFeedbackMask(CPyMOL * I, int action, int module, int mask){
1706 PyMOLreturn_status result = { PyMOLstatus_SUCCESS };
1707 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
1708 switch (action){
1709 case 0:
1710 G->Feedback->setMask(module, (uchar) mask);
1711 break;
1712 case 1:
1713 G->Feedback->enable(module, (uchar) mask);
1714 break;
1715 case 2:
1716 G->Feedback->disable(module, (uchar) mask);
1717 break;
1718 case 3:
1719 G->Feedback->push();
1720 break;
1721 case 4:
1722 G->Feedback->pop();
1723 break;
1724 }
1725 PYMOL_API_UNLOCK return result;
1726 }
1727
1728 static const CPyMOLOptions Defaults = {
1729 true, /* pmgui */
1730 #ifndef _PYMOL_NOPY
1731 true, /* internal_gui */
1732 #else
1733 false,
1734 #endif
1735 #ifndef _PYMOL_NOPY
1736 true, /* show_splash */
1737 #else
1738 false,
1739 #endif
1740 #ifndef _PYMOL_NOPY
1741 1, /* internal_feedback */
1742 #else
1743 0,
1744 #endif
1745 true, /* security */
1746 false, /* game mode */
1747 0, /* force_stereo */
1748 640, /* winX */
1749 480, /* winY */
1750 false, /* blue_line */
1751 0, /* winPX */
1752 175, /* winPY */
1753 true, /* external_gui */
1754 true, /* siginthand */
1755 false, /* reuse helper */
1756 false, /* auto reinitialize */
1757 false, /* keep thread alive */
1758 false, /* quiet */
1759 false, /* incentive product */
1760 "", /* after_load_script */
1761 0, /* multisample */
1762 1, /* window_visible */
1763 0, /* read_stdin */
1764 0, /* presentation */
1765 0, /* defer builds mode */
1766 0, /* full screen mode */
1767 -1, /* sphere mode */
1768 0, /* stereo capable */
1769 0, /* stereo mode */
1770 -1, /* zoom mode */
1771 0, /* launch_status */
1772 0, /* no quit */
1773 0, /* gldebug */
1774 false, /* no openvr stub */
1775 };
1776
PyMOLOptions_New(void)1777 CPyMOLOptions *PyMOLOptions_New(void)
1778 {
1779 CPyMOLOptions *result = NULL;
1780 result = pymol::calloc<CPyMOLOptions>(1);
1781 if(result)
1782 *result = Defaults;
1783 return result;
1784 }
1785
1786 #ifndef _PYMOL_NOPY
1787 void init_cmd(void);
1788
init_python(int argc,char * argv[])1789 static void init_python(int argc, char *argv[])
1790 {
1791 Py_Initialize();
1792 if(argv) {
1793 #if PY_MAJOR_VERSION < 3
1794 PySys_SetArgv(argc, argv);
1795 #endif
1796 }
1797
1798 PyEval_InitThreads();
1799
1800 PyRun_SimpleString("import sys");
1801 PyRun_SimpleString("import os");
1802 PyRun_SimpleString("sys.path.insert(0,os.environ['PYMOL_PATH']+'/modules')");
1803
1804 /* initialize our embedded C modules */
1805 init_cmd();
1806
1807 PyRun_SimpleString("import pymol");
1808
1809 /* parse arguments */
1810 PyRun_SimpleString("pymol.invocation.parse_args(sys.argv)");
1811 }
1812
1813
1814 /* WARNING: the routine below only works with the global singleton
1815 model -- not Python-enabled PyMOL instances */
1816
PyMOLOptions_NewWithPython(int argc,char * argv[])1817 CPyMOLOptions *PyMOLOptions_NewWithPython(int argc, char *argv[])
1818 {
1819 CPyMOLOptions *result = PyMOLOptions_New();
1820
1821 /* use Python to parse options based on the command line */
1822
1823 init_python(argc, argv);
1824 PGetOptions(result);
1825 return result;
1826 }
1827 #endif
1828
PyMOLOptions_Free(CPyMOLOptions * options)1829 void PyMOLOptions_Free(CPyMOLOptions * options)
1830 {
1831 FreeP(options);
1832 }
1833
PyMOL_ResetProgress(CPyMOL * I)1834 void PyMOL_ResetProgress(CPyMOL * I)
1835 {
1836 I->ProgressChanged = true;
1837 UtilZeroMem(I->Progress, sizeof(int) * 6);
1838 }
1839
PyMOL_SetProgress(CPyMOL * I,int offset,int current,int range)1840 void PyMOL_SetProgress(CPyMOL * I, int offset, int current, int range)
1841 {
1842 switch (offset) {
1843 case PYMOL_PROGRESS_SLOW:
1844 case PYMOL_PROGRESS_MED:
1845 case PYMOL_PROGRESS_FAST:
1846 if(current != I->Progress[offset]) {
1847 I->Progress[offset] = current;
1848 I->ProgressChanged = true;
1849 }
1850 if(range != I->Progress[offset + 1]) {
1851 I->Progress[offset + 1] = range;
1852 I->ProgressChanged = true;
1853 }
1854 }
1855 }
1856
PyMOL_GetProgress(CPyMOL * I,int * progress,int reset)1857 int PyMOL_GetProgress(CPyMOL * I, int *progress, int reset)
1858 {
1859 int a;
1860 int result = I->ProgressChanged;
1861 for(a = 0; a < PYMOL_PROGRESS_SIZE; a++) {
1862 progress[a] = I->Progress[a];
1863 }
1864 if(reset)
1865 I->ProgressChanged = false;
1866 return result;
1867 }
1868
PyMOL_GetProgressChanged(CPyMOL * I,int reset)1869 int PyMOL_GetProgressChanged(CPyMOL * I, int reset)
1870 {
1871 int result = I->ProgressChanged;
1872 if(reset)
1873 I->ProgressChanged = false;
1874 return result;
1875 }
1876
_PyMOL_New(void)1877 static CPyMOL *_PyMOL_New(void)
1878 {
1879 CPyMOL *result = NULL;
1880
1881 /* allocate global container */
1882
1883 if((result = pymol::calloc<CPyMOL>(1))) { /* all values initialized to zero */
1884
1885 if((result->G = pymol::calloc<PyMOLGlobals>(1))) {
1886
1887 result->G->PyMOL = result; /* store the instance pointer */
1888
1889 result->BusyFlag = false;
1890 result->InterruptFlag = false;
1891 PyMOL_ResetProgress(result);
1892
1893 #ifndef _PYMOL_NOPY
1894
1895 /* for the time being, the first PyMOL object created becomes
1896 the singleton object -- this is failsafe behavior designed to
1897 carry us through the transition to fully objectified PyMOL
1898 (PS note race in assignment covered by pymol2.pymol2_lock) */
1899
1900 if(!SingletonPyMOLGlobals) {
1901 SingletonPyMOLGlobals = result->G;
1902 }
1903 #endif
1904
1905 /* continue initialization */
1906
1907 } else {
1908 FreeP(result);
1909 }
1910 }
1911 return result;
1912 }
1913
_PyMOL_Config(CPyMOL * I)1914 static void _PyMOL_Config(CPyMOL * I)
1915 {
1916 #ifndef _PYMOL_NO_MAIN
1917 // also assign in PyMOL_DrawWithoutLock
1918 I->G->HaveGUI = I->G->Option->pmgui;
1919 #endif
1920 I->G->Security = I->G->Option->security;
1921 }
1922
PyMOL_New(void)1923 CPyMOL *PyMOL_New(void)
1924 {
1925 CPyMOL *result = _PyMOL_New();
1926 if(result && result->G) {
1927 result->G->Option = pymol::calloc<CPyMOLOptions>(1);
1928 if(result->G->Option)
1929 (*result->G->Option) = Defaults;
1930 _PyMOL_Config(result);
1931 }
1932 return result;
1933 }
1934
PyMOL_NewWithOptions(const CPyMOLOptions * option)1935 CPyMOL *PyMOL_NewWithOptions(const CPyMOLOptions * option)
1936 {
1937 CPyMOL *result = _PyMOL_New();
1938 if(result && result->G) {
1939 result->G->Option = pymol::calloc<CPyMOLOptions>(1);
1940 if(result->G->Option)
1941 *(result->G->Option) = *option;
1942 _PyMOL_Config(result);
1943 }
1944 result->G->StereoCapable = option->stereo_capable;
1945 return result;
1946 }
1947
PyMOL_Start(CPyMOL * I)1948 void PyMOL_Start(CPyMOL * I)
1949 {
1950 PyMOLGlobals *G = I->G;
1951
1952 // It's possible to change this from Python, functions which rely on
1953 // C locale should reset it before doing printf, atof, etc.
1954 std::setlocale(LC_NUMERIC, "C");
1955
1956 G->Context = OVContext_New();
1957 G->Lexicon = OVLexicon_New(G->Context->heap);
1958
1959 if(OVreturn_IS_ERROR(PyMOL_InitAPI(I))) {
1960 printf("ERROR: PyMOL internal C API initialization failed.\n");
1961 }
1962
1963 // global lexicon "constants"
1964 #define LEX_CONSTANTS_IMPL
1965 #include "lex_constants.h"
1966
1967 G->Feedback = new CFeedback(G, G->Option->quiet);
1968 WordInit(G);
1969 UtilInit(G);
1970 ColorInit(G);
1971 CGORendererInit(G);
1972 ShaderMgrInit(G);
1973 SettingInitGlobal(G, true, true, false);
1974 SettingSetGlobal_i(G, cSetting_internal_gui, G->Option->internal_gui);
1975 SettingSetGlobal_i(G, cSetting_internal_feedback, G->Option->internal_feedback);
1976 TextureInit(G);
1977 TypeInit(G);
1978 TextInit(G);
1979 CharacterInit(G);
1980 PlugIOManagerInit(G);
1981 SphereInit(G);
1982 // OpenVRInit() called in ExecutiveStereo
1983 OrthoInit(G, G->Option->show_splash);
1984 SceneInit(G);
1985 MovieScenesInit(G);
1986 WizardInit(G); /* must come after ortho & scene */
1987 G->Movie = new CMovie(G);
1988 G->SelectorMgr = new CSelectorManager();
1989 G->Selector = new CSelector(G, G->SelectorMgr);
1990 SeqInit(G);
1991 SeekerInit(G);
1992 ButModeInit(G);
1993 ControlInit(G);
1994 AtomInfoInit(G);
1995 SculptCacheInit(G);
1996 VFontInit(G);
1997 ExecutiveInit(G);
1998 IsosurfInit(G);
1999 TetsurfInit(G);
2000 EditorInit(G);
2001 #ifdef TRACKER_UNIT_TEST
2002 TrackerUnitTest(G);
2003 #endif
2004
2005 I->DrawnFlag = false;
2006 I->RedisplayFlag = true;
2007 G->Ready = true;
2008 }
2009
2010 /* This function is necessary to be called from PyMOL_StartWithPython
2011 which is called before the PYMOL_API is instantiated, thus
2012 it is not necessary (and you can't) lock the API */
PyMOL_ConfigureShadersGL_WithoutLock(CPyMOL * I)2013 void PyMOL_ConfigureShadersGL_WithoutLock(CPyMOL * I){
2014 I->done_ConfigureShaders = false;
2015 // ShaderMgr->Config() moved to PyMOL_DrawWithoutLock
2016 }
2017
2018 /* This function is called from CMol and needs to lock
2019 the PYMOL_API */
PyMOL_ConfigureShadersGL(CPyMOL * I)2020 void PyMOL_ConfigureShadersGL(CPyMOL * I){
2021 PYMOL_API_LOCK
2022 PyMOL_ConfigureShadersGL_WithoutLock(I);
2023 PYMOL_API_UNLOCK
2024 }
2025
2026 #ifndef _PYMOL_NOPY
2027
PyMOL_StartWithPython(CPyMOL * I)2028 void PyMOL_StartWithPython(CPyMOL * I)
2029 {
2030 PyMOL_Start(I);
2031
2032 /* now locate all the C to Python function hooks and objects we need */
2033
2034 PInit(I->G, false);
2035
2036 /* and begin the initialization sequence */
2037
2038 I->PythonInitStage = 1;
2039 }
2040
2041 #endif
2042
PyMOL_Stop(CPyMOL * I)2043 void PyMOL_Stop(CPyMOL * I)
2044 {
2045 PyMOLGlobals *G = I->G;
2046 G->Terminating = true;
2047 TetsurfFree(G);
2048 IsosurfFree(G);
2049 WizardFree(G);
2050 EditorFree(G);
2051 ExecutiveFree(G);
2052 VFontFree(G);
2053 SculptCacheFree(G);
2054 AtomInfoFree(G);
2055 ButModeFree(G);
2056 ControlFree(G);
2057 SeekerFree(G);
2058 SeqFree(G);
2059 DeleteP(G->Selector);
2060 DeleteP(G->SelectorMgr);
2061 DeleteP(G->Movie);
2062 SceneFree(G);
2063 MovieScenesFree(G);
2064 OrthoFree(G);
2065 #ifdef _PYMOL_OPENVR
2066 OpenVRFree(G);
2067 #endif
2068 DeleteP(G->ShaderMgr);
2069 SettingFreeGlobal(G);
2070 CharacterFree(G);
2071 TextFree(G);
2072 TypeFree(G);
2073 TextureFree(G);
2074 SphereFree(G);
2075 PlugIOManagerFree(G);
2076 PFree(G);
2077 CGORendererFree(G);
2078 ColorFree(G);
2079 UtilFree(G);
2080 WordFree(G);
2081 DeleteP(G->Feedback);
2082
2083 PyMOL_PurgeAPI(I);
2084 /* printf("%d \n", OVLexicon_GetNActive(G->Lexicon)); */
2085 OVLexicon_Del(G->Lexicon);
2086 OVContext_Del(G->Context);
2087 }
2088
PyMOL_Free(CPyMOL * I)2089 void PyMOL_Free(CPyMOL * I)
2090 {
2091 #if !defined(_PYMOL_ACTIVEX) && !defined(_MACPYMOL_XCODE)
2092 PYMOL_API_LOCK
2093 #endif
2094 /* take PyMOL down gracefully */
2095 PyMOLOptions_Free(I->G->Option);
2096
2097 #ifndef _PYMOL_NOPY
2098 FreeP(I->G->P_inst);
2099 if(I->G == SingletonPyMOLGlobals)
2100 SingletonPyMOLGlobals = NULL;
2101 #endif
2102
2103 FreeP(I->G);
2104 FreeP(I);
2105 return;
2106 #if !defined(_PYMOL_ACTIVEX) && !defined(_MACPYMOL_XCODE)
2107 PYMOL_API_UNLOCK;
2108 #endif
2109 }
2110
PyMOL_GetGlobals(CPyMOL * I)2111 struct _PyMOLGlobals *PyMOL_GetGlobals(CPyMOL * I)
2112 {
2113 return I->G;
2114 }
2115
PyMOL_GetGlobalsHandle(CPyMOL * I)2116 struct _PyMOLGlobals **PyMOL_GetGlobalsHandle(CPyMOL * I)
2117 {
2118 return &(I->G);
2119 }
2120
PyMOL_LockAPIAndUnblock(CPyMOL * I)2121 void PyMOL_LockAPIAndUnblock(CPyMOL * I)
2122 {
2123 PyMOLGlobals *G = I->G;
2124 (void)G;
2125 PLockAPIAndUnblock(G);
2126 }
2127
PyMOL_BlockAndUnlockAPI(CPyMOL * I)2128 void PyMOL_BlockAndUnlockAPI(CPyMOL * I)
2129 {
2130 PyMOLGlobals *G = I->G;
2131 (void)G;
2132 PBlockAndUnlockAPI(G);
2133 }
2134
PyMOL_AdaptToHardware(CPyMOL * I)2135 void PyMOL_AdaptToHardware(CPyMOL * I)
2136 {
2137 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
2138 if(G->HaveGUI) {
2139 PyMOL_PushValidContext(I);
2140 {
2141 char *vendor = (char *) glGetString(GL_VENDOR);
2142 char *renderer = (char *) glGetString(GL_RENDERER);
2143 char *version = (char *) glGetString(GL_VERSION);
2144 if(vendor && version) {
2145 /* work around broken lighting under Windows GDI Generic */
2146 if((strcmp(vendor, "Microsoft Corporation") == 0) &&
2147 (strcmp(renderer, "GDI Generic") == 0)) {
2148 ExecutiveSetSettingFromString(I->G, cSetting_light_count, "1", "", 0, 1, 0);
2149 ExecutiveSetSettingFromString(I->G, cSetting_spec_direct, "0.7", "", 0, 1, 0);
2150 }
2151 }
2152 }
2153 PyMOL_PopValidContext(I);
2154 }
2155 PYMOL_API_UNLOCK}
2156
setup_gl_state(void)2157 static void setup_gl_state(void)
2158 {
2159
2160 /* get us into a well defined GL state */
2161
2162 /*glMatrixMode(GL_PROJECTION);
2163 glLoadIdentity();
2164 glMatrixMode(GL_MODELVIEW);
2165 glLoadIdentity(); */
2166
2167 #ifndef PURE_OPENGL_ES_2
2168 glDisable(GL_ALPHA_TEST);
2169 glDisable(GL_COLOR_LOGIC_OP);
2170 glDisable(GL_COLOR_MATERIAL);
2171 glDisable(GL_FOG);
2172 glDisable(GL_LIGHTING);
2173 glDisable(GL_LIGHT0);
2174 glDisable(GL_LIGHT1);
2175 glDisable(GL_LINE_SMOOTH);
2176 glDisable(GL_NORMALIZE);
2177 #endif
2178
2179 glDisable(GL_BLEND);
2180 glDisable(GL_CULL_FACE);
2181 glDisable(GL_DEPTH_TEST);
2182 glDisable(GL_DITHER);
2183 #ifndef PURE_OPENGL_ES_2
2184 glDisable(GL_POLYGON_SMOOTH);
2185 #endif
2186 }
2187 void PyMOL_DrawWithoutLock(CPyMOL * I);
2188
PyMOL_Draw(CPyMOL * I)2189 void PyMOL_Draw(CPyMOL * I){
2190 PYMOL_API_LOCK_MODAL
2191 PyMOL_DrawWithoutLock(I);
2192 PYMOL_API_UNLOCK
2193 }
2194
PyMOL_LaunchStatus_Feedback(PyMOLGlobals * G)2195 static void PyMOL_LaunchStatus_Feedback(PyMOLGlobals * G)
2196 {
2197 G->LaunchStatus |= G->Option->launch_status;
2198
2199 if(G->StereoCapable) {
2200 OrthoAddOutput(G,
2201 " OpenGL quad-buffer stereo 3D detected and enabled.\n");;
2202 } else {
2203 if(G->LaunchStatus & cPyMOLGlobals_LaunchStatus_StereoFailed) {
2204 G->Feedback->addColored(
2205 "Error: The requested stereo 3D visualization mode is not available.\n",
2206 FB_Errors);
2207 }
2208 }
2209
2210 if(G->LaunchStatus & cPyMOLGlobals_LaunchStatus_MultisampleFailed) {
2211 G->Feedback->addColored(
2212 "Error: The requested multisampling mode is not available.\n",
2213 FB_Errors);
2214 }
2215 }
2216
2217 #ifndef PURE_OPENGL_ES_2
check_gl_stereo_capable(PyMOLGlobals * G)2218 static void check_gl_stereo_capable(PyMOLGlobals * G)
2219 {
2220 // quad buffer stereo available?
2221 GLboolean state;
2222 glGetBooleanv(GL_STEREO, &state);
2223 G->StereoCapable = state || G->Option->force_stereo > 0;
2224 if (!state && G->Option->force_stereo > 0) {
2225 printf("Warning: forcing stereo despite GL_STEREO=0\n");
2226 }
2227
2228 // stereo request feedback
2229 if (state && G->Option->stereo_mode == cStereo_default) {
2230 SettingSetGlobal_i(G, cSetting_stereo_mode, cStereo_quadbuffer);
2231 } else if (!state && G->Option->stereo_mode == cStereo_quadbuffer) {
2232 G->LaunchStatus |= cPyMOLGlobals_LaunchStatus_StereoFailed;
2233 }
2234
2235 // multisample request feedback
2236 if (G->Option->multisample) {
2237 GLint samplebuffers = 0;
2238 glGetIntegerv(GL_SAMPLE_BUFFERS, &samplebuffers);
2239 if (!samplebuffers) {
2240 G->LaunchStatus |= cPyMOLGlobals_LaunchStatus_MultisampleFailed;
2241 }
2242 }
2243
2244 // GL_BACK if GL_DOUBLEBUFFER else GL_FRONT
2245 // With QOpenGLWidget -> framebuffer object
2246 GLint buf;
2247 glGetIntegerv(GL_DRAW_BUFFER0, &buf);
2248 if (!buf) {
2249 printf("Warning: GL_DRAW_BUFFER0=0 -> using GL_BACK\n");
2250 buf = GL_BACK;
2251 }
2252 G->DRAW_BUFFER0 = buf;
2253
2254 // double buffer check
2255 glGetBooleanv(GL_DOUBLEBUFFER, &state);
2256 if (!state && buf <= GL_BACK) {
2257 printf("Warning: GL_DOUBLEBUFFER=0\n");
2258 }
2259
2260 // default framebuffer
2261 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buf);
2262 G->ShaderMgr->default_framebuffer_id = buf;
2263 }
2264 #endif
2265
PyMOL_DrawWithoutLock(CPyMOL * I)2266 void PyMOL_DrawWithoutLock(CPyMOL * I)
2267 {
2268 if (!I->done_ConfigureShaders) {
2269 I->done_ConfigureShaders = true;
2270
2271 I->G->HaveGUI = I->G->Option->pmgui;
2272
2273 #ifndef PURE_OPENGL_ES_2
2274 // stereo test with PyQt5 on Linux is broken (QTBUG-59636), so we
2275 // test for stereo here
2276 if (I->G->HaveGUI)
2277 {
2278 check_gl_stereo_capable(I->G);
2279 }
2280 #endif
2281
2282 PyMOL_LaunchStatus_Feedback(I->G);
2283
2284 I->G->ShaderMgr->Config();
2285
2286 // OpenGL debugging (glewInit must be called first)
2287 if (I->G->Option->gldebug) {
2288 #ifdef GL_DEBUG_OUTPUT
2289 if (!glDebugMessageCallback) {
2290 printf("glDebugMessageCallback not available\n");
2291 } else {
2292 glDebugMessageCallback(gl_debug_proc, NULL);
2293 glEnable(GL_DEBUG_OUTPUT);
2294 }
2295 #else
2296 printf("GL_DEBUG_OUTPUT not available\n");
2297 #endif
2298 }
2299 }
2300
2301 PyMOLGlobals * G = I->G;
2302 if(I->ModalDraw) {
2303 if(G->HaveGUI) {
2304 PyMOL_PushValidContext(I);
2305 setup_gl_state();
2306 }
2307 {
2308 PyMOLModalDrawFn *fn = I->ModalDraw;
2309 I->ModalDraw = NULL; /* always resets to NULL! */
2310 fn(G);
2311 }
2312
2313 if(G->HaveGUI) {
2314 PyMOL_PopValidContext(I);
2315 }
2316 } else {
2317
2318 if(I->DraggedFlag) {
2319 if(ControlIdling(I->G)) {
2320 ExecutiveSculptIterateAll(I->G);
2321 }
2322 I->DraggedFlag = false;
2323 }
2324
2325 if(G->HaveGUI) {
2326 PyMOL_PushValidContext(I);
2327
2328 setup_gl_state();
2329
2330 if(!I->DrawnFlag) {
2331 SceneSetCardInfo(G, (char *) glGetString(GL_VENDOR),
2332 (char *) glGetString(GL_RENDERER),
2333 (char *) glGetString(GL_VERSION));
2334 if(G->Option->show_splash && !G->Option->quiet) {
2335
2336 PRINTFB(G, FB_OpenGL, FB_Results)
2337 " OpenGL graphics engine:\n"
2338 " GL_VENDOR: %s\n"
2339 " GL_RENDERER: %s\n"
2340 " GL_VERSION: %s\n",
2341 (char *) glGetString(GL_VENDOR),
2342 (char *) glGetString(GL_RENDERER),
2343 (char *) glGetString(GL_VERSION) ENDFB(G);
2344 if(Feedback(G, FB_OpenGL, FB_Blather)) {
2345 printf(" GL_EXTENSIONS: %s\n", (char *) glGetString(GL_EXTENSIONS));
2346 }
2347 }
2348 I->DrawnFlag = true;
2349 }
2350 } else {
2351 I->DrawnFlag = true;
2352 }
2353
2354 I->RedisplayFlag = false;
2355
2356 OrthoBusyPrime(G);
2357 ExecutiveDrawNow(G);
2358
2359 if(I->ImageRequestedFlag) {
2360 if(SceneHasImage(G)) {
2361 I->ImageReadyFlag = true;
2362 I->ImageRequestedFlag = false;
2363 } else {
2364 I->ImageReadyFlag = false;
2365 }
2366 } else if(I->ImageReadyFlag) {
2367 if(!SceneHasImage(G))
2368 I->ImageReadyFlag = false;
2369 }
2370
2371 if(G->HaveGUI)
2372 PyMOL_PopValidContext(I);
2373 }
2374 }
2375
PyMOL_Key(CPyMOL * I,unsigned char k,int x,int y,int modifiers)2376 void PyMOL_Key(CPyMOL * I, unsigned char k, int x, int y, int modifiers)
2377 {
2378 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
2379 if(!WizardDoKey(G, k, x, y, modifiers))
2380 OrthoKey(G, k, x, y, modifiers);
2381 PyMOL_NeedRedisplay(G->PyMOL);
2382 PYMOL_API_UNLOCK}
2383
PyMOL_Special(CPyMOL * I,int k,int x,int y,int modifiers)2384 void PyMOL_Special(CPyMOL * I, int k, int x, int y, int modifiers)
2385 {
2386 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
2387
2388 int grabbed = false;
2389 char buffer[255];
2390 (void)buffer;
2391 if(!grabbed)
2392 grabbed = WizardDoSpecial(G, (unsigned char) k, x, y, modifiers);
2393
2394 switch (k) {
2395 case P_GLUT_KEY_UP:
2396 case P_GLUT_KEY_DOWN:
2397 grabbed = 1;
2398 OrthoSpecial(G, k, x, y, modifiers);
2399 break;
2400 case P_GLUT_KEY_LEFT:
2401 case P_GLUT_KEY_RIGHT:
2402 if(OrthoArrowsGrabbed(G)) {
2403 grabbed = 1;
2404 OrthoSpecial(G, k, x, y, modifiers);
2405 }
2406 break;
2407 }
2408
2409 #ifndef _PYMOL_NOPY
2410 if(!grabbed) {
2411 sprintf(buffer, "_special %d,%d,%d,%d", k, x, y, modifiers);
2412 PLog(G, buffer, cPLog_pml);
2413 PParse(G, buffer);
2414 PFlush(G);
2415 }
2416 #endif
2417
2418 PYMOL_API_UNLOCK}
2419
PyMOL_Reshape(CPyMOL * I,int width,int height,int force)2420 void PyMOL_Reshape(CPyMOL * I, int width, int height, int force)
2421 {
2422 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
2423
2424 G->Option->winX = width;
2425 G->Option->winY = height;
2426
2427 OrthoReshape(G, width, height, force);
2428 PYMOL_API_UNLOCK}
2429
PyMOL_Idle(CPyMOL * I)2430 int PyMOL_Idle(CPyMOL * I)
2431 {
2432 int did_work = false;
2433 PYMOL_API_TRYLOCK PyMOLGlobals * G = I->G;
2434
2435 I->DraggedFlag = false;
2436 if(I->IdleAndReady < IDLE_AND_READY) {
2437 if(I->DrawnFlag)
2438 I->IdleAndReady++;
2439 }
2440 if(I->FakeDragFlag == 1) {
2441 I->FakeDragFlag = false;
2442 OrthoFakeDrag(G);
2443 did_work = true;
2444 }
2445
2446 if(ControlIdling(G)) {
2447 ExecutiveSculptIterateAll(G);
2448 ControlSdofIterate(G);
2449 did_work = true;
2450 }
2451
2452 SceneIdle(G);
2453
2454 if(SceneRovingCheckDirty(G)) {
2455 SceneRovingUpdate(G);
2456 did_work = true;
2457 }
2458 #ifndef _PYMOL_NOPY
2459 if(PFlush(G)) {
2460 did_work = true;
2461 }
2462
2463 if(I->PythonInitStage > 0) {
2464 if(I->PythonInitStage < 2) {
2465 I->PythonInitStage++;
2466 } else {
2467 I->PythonInitStage = -1;
2468 PBlock(G);
2469
2470 PXDecRef(PYOBJECT_CALLMETHOD
2471 (G->P_inst->obj, "adapt_to_hardware", "O", G->P_inst->obj));
2472
2473 if(PyErr_Occurred())
2474 PyErr_Print();
2475
2476 PXDecRef(PYOBJECT_CALLMETHOD(G->P_inst->obj, "exec_deferred", "O", G->P_inst->obj));
2477
2478 if(PyErr_Occurred())
2479 PyErr_Print();
2480
2481 PUnblock(G);
2482 PFlush(G);
2483 }
2484 }
2485 #endif
2486
2487 /* reset the interrupt flag if we're not doing anything */
2488
2489 if(!(did_work || I->ModalDraw))
2490 if(PyMOL_GetInterrupt(I, false))
2491 PyMOL_SetInterrupt(I, false);
2492
2493 PYMOL_API_UNLOCK_NO_FLUSH return (did_work || I->ModalDraw);
2494 }
2495
PyMOL_ExpireIfIdle(CPyMOL * I)2496 void PyMOL_ExpireIfIdle(CPyMOL * I)
2497 {
2498 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
2499 int final_init_done = true;
2500 #ifndef _PYMOL_NOPY
2501 final_init_done = (I->PythonInitStage == -1);
2502 #endif
2503
2504 if(!G->HaveGUI) {
2505 if(final_init_done) {
2506 if(!OrthoCommandWaiting(G)) {
2507 if((!G->Option->keep_thread_alive) && (!G->Option->read_stdin)) {
2508 I->ExpireCount++;
2509 if(I->ExpireCount == 10) {
2510 PParse(G, "_quit");
2511 }
2512 }
2513 }
2514 }
2515 }
2516 PYMOL_API_UNLOCK;
2517 }
2518
PyMOL_NeedFakeDrag(CPyMOL * I)2519 void PyMOL_NeedFakeDrag(CPyMOL * I)
2520 {
2521 I->FakeDragFlag = true;
2522 }
2523
PyMOL_NeedRedisplay(CPyMOL * I)2524 void PyMOL_NeedRedisplay(CPyMOL * I)
2525 {
2526 I->RedisplayFlag = true;
2527 }
2528
PyMOL_NeedSwap(CPyMOL * I)2529 void PyMOL_NeedSwap(CPyMOL * I)
2530 {
2531 I->SwapFlag = true;
2532 }
2533
PyMOL_NeedReshape(CPyMOL * I,int mode,int x,int y,int width,int height)2534 void PyMOL_NeedReshape(CPyMOL * I, int mode, int x, int y, int width, int height)
2535 {
2536 PyMOLGlobals *G = I->G;
2537 if(width < 0) {
2538 if (!G->HaveGUI)
2539 return;
2540
2541 width = SceneGetBlock(G)->getWidth();
2542 if(SettingGetGlobal_b(G, cSetting_internal_gui))
2543 width += DIP2PIXEL(SettingGetGlobal_i( G, cSetting_internal_gui_width));
2544 }
2545
2546 /* if height is negative, force a reshape based on the current height */
2547
2548 if(height < 0) {
2549 int internal_feedback;
2550 height = SceneGetBlock(G)->getHeight();
2551 internal_feedback = SettingGetGlobal_i(G, cSetting_internal_feedback);
2552 if(internal_feedback)
2553 height += (internal_feedback - 1) * cOrthoLineHeight + cOrthoBottomSceneMargin;
2554 if(SettingGetGlobal_b(G, cSetting_seq_view)
2555 && !SettingGetGlobal_b(G, cSetting_seq_view_overlay)) {
2556 height += SeqGetHeight(G);
2557 }
2558 height += MovieGetPanelHeight(G);
2559 }
2560
2561 if(G->HaveGUI) {
2562 float sf = DIP2PIXEL(1);
2563
2564 I->Reshape[1] = x / sf;
2565 I->Reshape[2] = y / sf;
2566 I->Reshape[3] = width / sf;
2567 I->Reshape[4] = height / sf;
2568
2569 I->ReshapeFlag = true;
2570 I->Reshape[0] = mode;
2571 PyMOL_NeedRedisplay(I);
2572 } else {
2573 /* if no gui, then force immediate reshape */
2574 PyMOLGlobals *G = I->G;
2575
2576 G->Option->winX = width;
2577 G->Option->winY = height;
2578
2579 OrthoReshape(G, width, height, true);
2580 }
2581 }
2582
PyMOL_GetIdleAndReady(CPyMOL * I)2583 int PyMOL_GetIdleAndReady(CPyMOL * I)
2584 {
2585 return (I->IdleAndReady == IDLE_AND_READY);
2586 }
2587
PyMOL_GetReshape(CPyMOL * I)2588 int PyMOL_GetReshape(CPyMOL * I)
2589 {
2590 return I->ReshapeFlag;
2591 }
2592
PyMOL_GetReshapeInfo(CPyMOL * I,int reset)2593 PyMOLreturn_int_array PyMOL_GetReshapeInfo(CPyMOL * I, int reset)
2594 {
2595 PyMOLreturn_int_array result = { PyMOLstatus_SUCCESS, PYMOL_RESHAPE_SIZE, NULL };
2596 PYMOL_API_LOCK
2597 if(reset)
2598 I->ReshapeFlag = false;
2599 result.array = VLAlloc(int, PYMOL_RESHAPE_SIZE);
2600 if(!result.array) {
2601 result.status = PyMOLstatus_FAILURE;
2602 } else {
2603 int a;
2604 for(a = 0; a < PYMOL_RESHAPE_SIZE; a++)
2605 result.array[a] = I->Reshape[a];
2606 }
2607
2608 PYMOL_API_UNLOCK
2609 return result;
2610 }
2611
PyMOL_SetPassive(CPyMOL * I,int onOff)2612 void PyMOL_SetPassive(CPyMOL * I, int onOff)
2613 {
2614 I->PassiveFlag = onOff;
2615 }
2616
PyMOL_SetClickReady(CPyMOL * I,const char * name,int index,int button,int mod,int x,int y,const float * pos,int state)2617 void PyMOL_SetClickReady(CPyMOL * I, const char *name, int index, int button, int mod, int x,
2618 int y, const float *pos, int state)
2619 {
2620
2621 if(name && name[0] && (index >= 0)) {
2622 I->ClickReadyFlag = true;
2623 strcpy(I->ClickedObject, name);
2624 I->ClickedIndex = index;
2625 I->ClickedButton = button;
2626 I->ClickedModifiers = mod;
2627 I->ClickedX = x;
2628 I->ClickedY = y;
2629 } else {
2630 I->ClickedObject[0] = 0;
2631 I->ClickReadyFlag = true;
2632 I->ClickedX = x;
2633 I->ClickedY = y;
2634 I->ClickedIndex = index;
2635 I->ClickedButton = button;
2636 I->ClickedModifiers = mod;
2637 }
2638 if(pos) {
2639 I->ClickedHavePos = true;
2640 copy3f(pos, I->ClickedPos);
2641 I->ClickedPosState = state;
2642 } else {
2643 I->ClickedHavePos = false;
2644 zero3f(I->ClickedPos);
2645 I->ClickedPosState = 0;
2646 }
2647 }
2648
PyMOL_GetClickReady(CPyMOL * I,int reset)2649 int PyMOL_GetClickReady(CPyMOL * I, int reset)
2650 {
2651 int result = I->ClickReadyFlag;
2652 if(reset) {
2653 I->ClickReadyFlag = false;
2654 }
2655 return result;
2656 }
2657
PyMOL_GetClickString(CPyMOL * I,int reset)2658 char *PyMOL_GetClickString(CPyMOL * I, int reset)
2659 {
2660 char *result = NULL;
2661 PYMOL_API_LOCK int ready = I->ClickReadyFlag;
2662 if(reset)
2663 I->ClickReadyFlag = false;
2664 if(ready) {
2665 result = pymol::malloc<char>(OrthoLineLength + 1);
2666 if(result) {
2667 WordType butstr = "left", modstr = "", posstr = "";
2668 result[0] = 0;
2669 switch (I->ClickedButton) {
2670 case P_GLUT_SINGLE_LEFT:
2671 strcpy(butstr, "single_left");
2672 break;
2673 case P_GLUT_SINGLE_MIDDLE:
2674 strcpy(butstr, "single_middle");
2675 break;
2676 case P_GLUT_SINGLE_RIGHT:
2677 strcpy(butstr, "single_right");
2678 break;
2679 case P_GLUT_DOUBLE_LEFT:
2680 strcpy(butstr, "double_left");
2681 break;
2682 case P_GLUT_DOUBLE_MIDDLE:
2683 strcpy(butstr, "double_middle");
2684 break;
2685 case P_GLUT_DOUBLE_RIGHT:
2686 strcpy(butstr, "double_right");
2687 break;
2688 }
2689 if(cOrthoCTRL & I->ClickedModifiers) {
2690 if(modstr[0])
2691 strcat(modstr, " ");
2692 strcat(modstr, "ctrl");
2693 }
2694 if(cOrthoALT & I->ClickedModifiers) {
2695 if(modstr[0])
2696 strcat(modstr, " ");
2697 strcat(modstr, "alt");
2698 }
2699 if(cOrthoSHIFT & I->ClickedModifiers) {
2700 if(modstr[0])
2701 strcat(modstr, " ");
2702 strcat(modstr, "shift");
2703 }
2704 if(I->ClickedHavePos) {
2705 sprintf(posstr,"px=%.7g\npy=%.7g\npz=%.7g\nstate=%d",I->ClickedPos[0],I->ClickedPos[1],I->ClickedPos[2],I->ClickedPosState);
2706 }
2707 if(!I->ClickedObject[0]) {
2708 sprintf(result,
2709 "type=none\nclick=%s\nmod_keys=%s\nx=%d\ny=%d\n%s",
2710 butstr, modstr, I->ClickedX, I->ClickedY,posstr);
2711 } else {
2712 ObjectMolecule *obj = ExecutiveFindObjectMoleculeByName(I->G, I->ClickedObject);
2713 if(obj && (I->ClickedIndex < obj->NAtom)) {
2714 AtomInfoType *ai = obj->AtomInfo + I->ClickedIndex;
2715 char inscode_str[2] = { ai->inscode, '\0' };
2716 sprintf(result,
2717 "type=object:molecule\nobject=%s\nindex=%d\nrank=%d\nid=%d\nsegi=%s\nchain=%s\nresn=%s\nresi=%d%s\nname=%s\nalt=%s\nclick=%s\nmod_keys=%s\nx=%d\ny=%d\n%s",
2718 I->ClickedObject,
2719 I->ClickedIndex + 1,
2720 ai->rank,
2721 ai->id,
2722 LexStr(I->G, ai->segi),
2723 LexStr(I->G, ai->chain),
2724 LexStr(I->G, ai->resn),
2725 ai->resv, inscode_str,
2726 LexStr(I->G, ai->name),
2727 ai->alt, butstr, modstr, I->ClickedX, I->ClickedY, posstr);
2728 }
2729 }
2730 }
2731 }
2732 PYMOL_API_UNLOCK return (result);
2733 }
2734
PyMOL_GetImageReady(CPyMOL * I,int reset)2735 int PyMOL_GetImageReady(CPyMOL * I, int reset)
2736 {
2737 int result = I->ImageReadyFlag;
2738 if(reset) {
2739 I->ImageReadyFlag = false;
2740 }
2741 return result;
2742 }
2743
PyMOL_GetImageInfo(CPyMOL * I)2744 PyMOLreturn_int_array PyMOL_GetImageInfo(CPyMOL * I)
2745 {
2746 PyMOLreturn_int_array result = { PyMOLstatus_SUCCESS, 2, NULL };
2747 PYMOL_API_LOCK result.array = VLAlloc(int, 2);
2748 if(!result.array) {
2749 result.status = PyMOLstatus_FAILURE;
2750 } else {
2751 std::tie(result.array[0], result.array[1]) = SceneGetImageSize(I->G);
2752 }
2753 PYMOL_API_UNLOCK return result;
2754 }
2755
PyMOL_GetImageData(CPyMOL * I,int width,int height,int row_bytes,void * buffer,int mode,int reset)2756 int PyMOL_GetImageData(CPyMOL * I,
2757 int width, int height,
2758 int row_bytes, void *buffer, int mode, int reset)
2759 {
2760 int ok = true;
2761 PYMOL_API_LOCK if(reset)
2762 I->ImageReadyFlag = false;
2763 ok = SceneCopyExternal(I->G, width, height, row_bytes, (unsigned char *) buffer, mode);
2764 PYMOL_API_UNLOCK return get_status_ok(ok);
2765 }
2766
PyMOL_GetImageDataReturned(CPyMOL * I,int width,int height,int row_bytes,int mode,int reset)2767 PyMOLreturn_int_array PyMOL_GetImageDataReturned(CPyMOL * I,
2768 int width, int height,
2769 int row_bytes, int mode, int reset)
2770 {
2771 PyMOLreturn_int_array result = { PyMOLstatus_SUCCESS, 0, NULL };
2772 int ok = true;
2773 int size;
2774 void *buffer;
2775 PYMOL_API_LOCK
2776 if(reset){
2777 I->ImageReadyFlag = false;
2778 }
2779 size = width*height;
2780 buffer = VLAlloc(int, size);
2781 ((int*)buffer)[0] = ('A'<<24)|('B'<<16)|('G'<<8)|'R';
2782 ok = SceneCopyExternal(I->G, width, height, row_bytes, (unsigned char *) buffer, mode);
2783 if(ok) {
2784 result.array = (int*) buffer;
2785 result.size = size;
2786 } else {
2787 result.status = PyMOLstatus_FAILURE;
2788 }
2789
2790 PYMOL_API_UNLOCK return result;
2791 }
2792
PyMOL_FreeResultString(CPyMOL * I,char * st)2793 int PyMOL_FreeResultString(CPyMOL * I, char *st)
2794 {
2795 PYMOL_API_LOCK FreeP(st);
2796 PYMOL_API_UNLOCK return get_status_ok((st != NULL));
2797 }
2798
PyMOL_GetRedisplay(CPyMOL * I,int reset)2799 int PyMOL_GetRedisplay(CPyMOL * I, int reset)
2800 {
2801 int result = false;
2802
2803 PYMOL_API_TRYLOCK PyMOLGlobals * G = I->G;
2804 result = I->RedisplayFlag;
2805
2806 if(result) {
2807 if(SettingGet_b(G, NULL, NULL, cSetting_defer_updates)) {
2808 result = false;
2809 } else {
2810 if(reset)
2811 I->RedisplayFlag = false;
2812 }
2813 }
2814 PYMOL_API_UNLOCK_NO_FLUSH return (result || I->ModalDraw); /* always true when ModalDraw is set */
2815 }
2816
PyMOL_GetPassive(CPyMOL * I,int reset)2817 int PyMOL_GetPassive(CPyMOL * I, int reset)
2818 { /* lock intentionally omitted */
2819 int result = I->PassiveFlag;
2820 if(reset)
2821 I->PassiveFlag = false;
2822 return result;
2823 }
2824
PyMOL_GetModalDraw(CPyMOL * I)2825 int PyMOL_GetModalDraw(CPyMOL * I)
2826 {
2827 if(I)
2828 return (I->ModalDraw != NULL);
2829 return false;
2830 }
2831
PyMOL_SetModalDraw(CPyMOL * I,PyMOLModalDrawFn * fn)2832 void PyMOL_SetModalDraw(CPyMOL * I, PyMOLModalDrawFn * fn)
2833 {
2834 I->ModalDraw = fn;
2835 }
2836
PyMOL_GetSwap(CPyMOL * I,int reset)2837 int PyMOL_GetSwap(CPyMOL * I, int reset)
2838 { /* lock intentionally omitted */
2839 int result = I->SwapFlag;
2840 if(reset)
2841 I->SwapFlag = false;
2842 return result;
2843 }
2844
PyMOL_GetBusy(CPyMOL * I,int reset)2845 int PyMOL_GetBusy(CPyMOL * I, int reset)
2846 { /* lock intentionally omitted */
2847 int result = I->BusyFlag;
2848 if(reset)
2849 PyMOL_SetBusy(I, false);
2850 return result;
2851 }
2852
PyMOL_SetBusy(CPyMOL * I,int value)2853 void PyMOL_SetBusy(CPyMOL * I, int value)
2854 { /* lock intentionally omitted */
2855 if(!I->BusyFlag)
2856 /* if we weren't busy before, then reset the progress indicators */
2857 PyMOL_ResetProgress(I);
2858
2859 I->BusyFlag = value;
2860 }
2861
PyMOL_GetInterrupt(CPyMOL * I,int reset)2862 int PyMOL_GetInterrupt(CPyMOL * I, int reset)
2863 { /* lock intentionally omitted */
2864 if(I) {
2865 int result = I->InterruptFlag;
2866
2867 if(reset)
2868 PyMOL_SetInterrupt(I, false);
2869 return result;
2870 } else
2871 return false;
2872 }
2873
PyMOL_SetInterrupt(CPyMOL * I,int value)2874 void PyMOL_SetInterrupt(CPyMOL * I, int value)
2875 { /* lock intentionally omitted */
2876 if(I) {
2877 I->InterruptFlag = value;
2878 if(I->G)
2879 I->G->Interrupt = value;
2880 }
2881 }
2882
PyMOL_Drag(CPyMOL * I,int x,int y,int modifiers)2883 void PyMOL_Drag(CPyMOL * I, int x, int y, int modifiers)
2884 {
2885 PYMOL_API_LOCK OrthoDrag(I->G, x, y, modifiers);
2886 I->DraggedFlag = true;
2887 PYMOL_API_UNLOCK}
2888
2889 /*
2890 * Mouse button and keyboard press handler
2891 *
2892 * button: mouse button or key code
2893 * state:
2894 * -2 = key press with GLUT_KEY_* special code
2895 * -1 = key press with ascii code
2896 * 0 = mouse down
2897 * 1 = mouse up
2898 * x, y: mouse pointer position
2899 * modifiers: SHIFT/CTRL/ALT bitmask
2900 */
PyMOL_Button(CPyMOL * I,int button,int state,int x,int y,int modifiers)2901 void PyMOL_Button(CPyMOL * I, int button, int state, int x, int y, int modifiers)
2902 {
2903 PYMOL_API_LOCK
2904 if (state == -1) {
2905 PyMOL_Key(I, (unsigned char)button, x, y, modifiers);
2906 } else if (state == -2) {
2907 PyMOL_Special(I, button, x, y, modifiers);
2908 } else {
2909 OrthoButton(I->G, button, state, x, y, modifiers);
2910 }
2911 PYMOL_API_UNLOCK}
2912
PyMOL_SetSwapBuffersFn(CPyMOL * I,PyMOLSwapBuffersFn * fn)2913 void PyMOL_SetSwapBuffersFn(CPyMOL * I, PyMOLSwapBuffersFn * fn)
2914 {
2915 I->SwapFn = fn;
2916 }
2917
PyMOL_SwapBuffers(CPyMOL * I)2918 void PyMOL_SwapBuffers(CPyMOL * I)
2919 {
2920 if(I->SwapFn && I->G->ValidContext) {
2921 I->SwapFn();
2922 I->SwapFlag = false;
2923 } else {
2924 I->SwapFlag = true;
2925 }
2926 }
2927
PyMOL_RunTest(CPyMOL * I,int group,int test)2928 void PyMOL_RunTest(CPyMOL * I, int group, int test)
2929 {
2930 PYMOL_API_LOCK TestPyMOLRun(I->G, group, test);
2931 PYMOL_API_UNLOCK}
2932
PyMOL_PushValidContext(CPyMOL * I)2933 void PyMOL_PushValidContext(CPyMOL * I)
2934 {
2935 if(I && I->G)
2936 I->G->ValidContext++;
2937 }
2938
PyMOL_PopValidContext(CPyMOL * I)2939 void PyMOL_PopValidContext(CPyMOL * I)
2940 {
2941 if(I && I->G && (I->G->ValidContext > 0))
2942 I->G->ValidContext--;
2943 }
2944
PyMOL_SetStereoCapable(CPyMOL * I,int stereoCapable)2945 void PyMOL_SetStereoCapable(CPyMOL * I, int stereoCapable){
2946 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
2947 G->StereoCapable = stereoCapable;
2948 if (SettingGetGlobal_b(I->G, cSetting_stereo_mode)==0){
2949 /* if users haven't set stereo_mode, then set it to default */
2950 if (G->StereoCapable){
2951 SettingSetGlobal_i(I->G, cSetting_stereo_mode, cStereo_quadbuffer); /* quadbuffer if we can */
2952 } else {
2953 SettingSetGlobal_i(I->G, cSetting_stereo_mode, cStereo_crosseye); /* otherwise crosseye by default */
2954 }
2955 } else if (G->StereoCapable && SettingGetGlobal_b(G, cSetting_stereo)){
2956 SettingSetGlobal_i(I->G, cSetting_stereo_mode, SettingGetGlobal_b(I->G, cSetting_stereo_mode));
2957 }
2958 SceneUpdateStereo(I->G);
2959 PYMOL_API_UNLOCK
2960 }
2961
PyMOL_InitializeCMol(CPyMOL * I)2962 void PyMOL_InitializeCMol(CPyMOL * I){
2963 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
2964 /* Set stereo_mode to 0, so that PyMOL_SetStereoCapable()
2965 can determine whether user has changed the stereo_mode. If
2966 users have not changed it, then set to quadbuffer if we can,
2967 or crosseye by default (see above) */
2968 SettingSetGlobal_i(G, cSetting_stereo_mode, 0);
2969 PYMOL_API_UNLOCK
2970 }
2971
PyMOL_SetDefaultMouse(CPyMOL * I)2972 void PyMOL_SetDefaultMouse(CPyMOL * I)
2973 {
2974 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
2975
2976 ButModeSet(G, cButModeLeftNone, cButModeRotXYZ);
2977 ButModeSet(G, cButModeMiddleNone, cButModeTransXY);
2978 ButModeSet(G, cButModeRightNone, cButModeTransZ);
2979
2980 ButModeSet(G, cButModeLeftShft, cButModePotentialClick);
2981 ButModeSet(G, cButModeMiddleShft, cButModePotentialClick);
2982 ButModeSet(G, cButModeRightShft, cButModeClipNF);
2983
2984 ButModeSet(G, cButModeLeftCtrl, cButModePotentialClick);
2985 ButModeSet(G, cButModeMiddleCtrl, cButModePotentialClick);
2986 ButModeSet(G, cButModeRightCtrl, cButModePotentialClick);
2987
2988 ButModeSet(G, cButModeLeftCtSh, cButModePotentialClick);
2989 ButModeSet(G, cButModeMiddleCtSh, cButModePotentialClick);
2990 ButModeSet(G, cButModeRightCtSh, cButModePotentialClick);
2991
2992 ButModeSet(G, cButModeWheelNone, cButModeScaleSlab);
2993 ButModeSet(G, cButModeWheelShft, cButModeMoveSlab);
2994 ButModeSet(G, cButModeWheelCtrl, cButModeMoveSlabAndZoom);
2995 ButModeSet(G, cButModeWheelCtSh, cButModeTransZ);
2996
2997 ButModeSet(G, cButModeMiddleCtSh, cButModeOrigAt); /* SET TWICE?!? */
2998
2999 ButModeSet(G, cButModeLeftSingle, cButModeSimpleClick);
3000 ButModeSet(G, cButModeMiddleSingle, cButModeCent);
3001 ButModeSet(G, cButModeRightSingle, cButModeSimpleClick);
3002
3003 ButModeSet(G, cButModeLeftDouble, cButModeSimpleClick);
3004 ButModeSet(G, cButModeRightDouble, cButModeSimpleClick);
3005
3006 {
3007 int a;
3008 for(a = cButModeLeftShftDouble; a <= cButModeRightCtrlAltShftSingle; a++) {
3009 ButModeSet(G, a, cButModeSimpleClick);
3010 }
3011 for(a = cButModeLeftAlt; a <= cButModeRightCtrlAltShft; a++) {
3012 ButModeSet(G, a, cButModePotentialClick);
3013 }
3014
3015 }
3016 G->Feedback->currentMask(FB_Scene) &= ~(FB_Results); /* suppress click messages */
3017 PYMOL_API_UNLOCK}
3018
PyMOL_CmdRock(CPyMOL * I,int mode)3019 PyMOLreturn_status PyMOL_CmdRock(CPyMOL * I, int mode){
3020 PyMOLreturn_status result = { PyMOLstatus_SUCCESS };
3021 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
3022 ControlRock(G, mode);
3023 PYMOL_API_UNLOCK return result;
3024 }
3025
3026
PyMOL_CmdGetNames(CPyMOL * I,int mode,const char * s0,int enabled_only)3027 PyMOLreturn_string_array PyMOL_CmdGetNames(CPyMOL * I, int mode, const char *s0, int enabled_only){
3028 PyMOLreturn_string_array result = { PyMOLstatus_FAILURE };
3029 PYMOL_API_LOCK PyMOLGlobals * G = I->G;
3030 result = return_result(ExecutiveGetNames(G, mode, enabled_only, s0));
3031 PYMOL_API_UNLOCK
3032 return (result);
3033 }
3034
PyMOL_CmdMapNew(CPyMOL * I,const char * name,int type,float grid_spacing,const char * selection,int state,int normalize,int zoom,int quiet)3035 PyMOLreturn_status PyMOL_CmdMapNew(CPyMOL * I, const char *name, int type, float grid_spacing,
3036 const char *selection, int state, int normalize,
3037 int zoom, int quiet){
3038 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
3039 float minCorner[3], maxCorner[3];
3040 PYMOL_API_LOCK
3041
3042 minCorner[0] = minCorner[1] = minCorner[2] = 0.;
3043 maxCorner[0] = maxCorner[1] = maxCorner[2] = 1.;
3044 auto res = ExecutiveMapNew(I->G, name, type, grid_spacing,
3045 selection, -1., minCorner, maxCorner, state, 0, quiet, 0, normalize, 1.,
3046 -1., 0.);
3047 result.status = get_status_ok(static_cast<bool>(res));
3048
3049 PYMOL_API_UNLOCK return result;
3050 }
3051
3052 #ifdef _PYMOL_LIB
PyMOL_SetIsEnabledCallback(CPyMOL * I,void * CallbackObject,void (* enabledCallback)(void *,const char *,int))3053 PyMOLreturn_status PyMOL_SetIsEnabledCallback(CPyMOL * I, void *CallbackObject, void (*enabledCallback)(void *, const char *, int )){
3054 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
3055 PYMOL_API_LOCK
3056 I->G->CallbackObject = CallbackObject;
3057 I->G->enabledCallback = enabledCallback;
3058 result.status = PyMOLstatus_SUCCESS;
3059 PYMOL_API_UNLOCK
3060 return result;
3061 }
3062
PyMOL_GetRepsInSceneForObject(CPyMOL * I,const char * name)3063 PyMOLreturn_int_array PyMOL_GetRepsInSceneForObject(CPyMOL * I, const char *name){
3064 PyMOLreturn_int_array result = { PyMOLstatus_SUCCESS, 0, NULL };
3065 int *retarr = 0;
3066 PYMOL_API_LOCK
3067 retarr = ExecutiveGetRepsInSceneForObject(I->G, name);
3068 if(!retarr) {
3069 result.status = PyMOLstatus_FAILURE;
3070 } else {
3071 result.size = VLAGetSize(retarr);
3072 result.array = retarr;
3073 }
3074 PYMOL_API_UNLOCK return result;
3075 }
3076
PyMOL_GetRepsForObject(CPyMOL * I,const char * name)3077 PyMOLreturn_int_array PyMOL_GetRepsForObject(CPyMOL * I, const char *name){
3078 PyMOLreturn_int_array result = { PyMOLstatus_SUCCESS, 0, NULL };
3079 int *retarr = 0;
3080 PYMOL_API_LOCK
3081 retarr = ExecutiveGetRepsForObject(I->G, name);
3082 if(!retarr) {
3083 result.status = PyMOLstatus_FAILURE;
3084 } else {
3085 result.size = VLAGetSize(retarr);
3086 result.array = retarr;
3087 }
3088 PYMOL_API_UNLOCK return result;
3089 }
3090
3091 static OVreturn_word get_button_code(CPyMOL * I, char *code);
3092 static OVreturn_word get_button_mod_code(CPyMOL * I, char *modcode);
3093 static OVreturn_word get_button_action_code(CPyMOL * I, char *actioncode);
3094 static OVreturn_word get_mouse_mode(CPyMOL * I, char *mousemode);
3095
PyMOL_SetButton(CPyMOL * I,const char * buttonarg,const char * modifierarg,const char * actionarg)3096 PyMOLreturn_status PyMOL_SetButton(CPyMOL * I, const char *buttonarg, const char *modifierarg, const char *actionarg){
3097 int ok = true;
3098 OVreturn_word button_num, but_mod_num, act_code;
3099 int but_code;
3100 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
3101 OrthoLineType button, modifier, action;
3102 PYMOL_API_LOCK
3103 UtilNCopyToLower(button, buttonarg, strlen(buttonarg)+1);
3104 UtilNCopyToLower(modifier, modifierarg, strlen(modifierarg)+1);
3105 UtilNCopyToLower(action, actionarg, strlen(actionarg)+1);
3106 ok = OVreturn_IS_OK(button_num = get_button_code(I, button));
3107 if (ok) ok = OVreturn_IS_OK((but_mod_num = get_button_mod_code(I, modifier)));
3108 if (ok) ok = OVreturn_IS_OK((act_code = get_button_action_code(I, action)));
3109
3110 if (ok){
3111 /* This is directly from the button() function in controlling.py */
3112 if (button_num.word < 3){ // normal button (L,M,R)
3113 if (but_mod_num.word < 4){
3114 // none, shft, ctrl, ctsh
3115 but_code = button_num.word + 3*but_mod_num.word;
3116 } else {
3117 // alt, alsh, alct, alcs
3118 but_code = button_num.word + 68 + 3*(but_mod_num.word-4);
3119 }
3120 } else if (button_num.word < 4){ // wheel
3121 if (but_mod_num.word < 4){
3122 // none, shft, ctrl, ctsh
3123 but_code = 12 + but_mod_num.word;
3124 } else {
3125 but_code = 64 + but_mod_num.word - 4;
3126 }
3127 } else {
3128 // single and double clicks
3129 but_code = (16 + button_num.word -4) + but_mod_num.word * 6;
3130 }
3131 ButModeSet(I->G, but_code, act_code.word);
3132 result.status = PyMOLstatus_SUCCESS;
3133 }
3134 PYMOL_API_UNLOCK return result;
3135 }
3136 #include "buttonmodes.h"
3137
PyMOL_SetMouseButtonMode(CPyMOL * I,const char * modename)3138 PyMOLreturn_status PyMOL_SetMouseButtonMode(CPyMOL * I, const char *modename){
3139 int ok = true, i, start;
3140 OVreturn_word mode;
3141 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
3142
3143 PYMOL_API_LOCK
3144 {
3145 char *nmodename = (char*)malloc(strlen(modename)+1);
3146 UtilNCopyToLower((char*)nmodename, modename, strlen(modename)+1);
3147 ok = OVreturn_IS_OK(mode = get_mouse_mode(I, (char*)nmodename));
3148 free(nmodename);
3149 }
3150 if (ok){
3151 result.status = PyMOLstatus_SUCCESS;
3152 {
3153 int a;
3154 /* for Button modes, first initialize all buttons, so that
3155 previous functionality does not linger */
3156 for(a = 0; a < cButModeInputCount; a++) {
3157 ButModeSet(I->G, a, initial_button_modes[a]);
3158 }
3159 }
3160 start = button_mode_start[mode.word];
3161 for (i=0; i<n_button_mode[mode.word]; i++, start+=2){
3162 ButModeSet(I->G, all_buttons[start], all_buttons[start+1]);
3163 }
3164 }
3165 PYMOL_API_UNLOCK return result;
3166 }
3167
get_button_code(CPyMOL * I,char * code)3168 static OVreturn_word get_button_code(CPyMOL * I, char *code)
3169 {
3170 OVreturn_word result;
3171 if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, code))))
3172 return result;
3173 return OVOneToOne_GetForward(I->MouseButtonCodeLexicon, result.word);
3174 }
get_button_mod_code(CPyMOL * I,char * modcode)3175 static OVreturn_word get_button_mod_code(CPyMOL * I, char *modcode)
3176 {
3177 OVreturn_word result;
3178 if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, modcode))))
3179 return result;
3180 return OVOneToOne_GetForward(I->MouseButtonModCodeLexicon, result.word);
3181 }
get_button_action_code(CPyMOL * I,char * actioncode)3182 static OVreturn_word get_button_action_code(CPyMOL * I, char *actioncode)
3183 {
3184 OVreturn_word result;
3185 if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, actioncode))))
3186 return result;
3187 return OVOneToOne_GetForward(I->MouseButtonActionCodeLexicon, result.word);
3188 }
get_mouse_mode(CPyMOL * I,char * mousemode)3189 static OVreturn_word get_mouse_mode(CPyMOL * I, char *mousemode)
3190 {
3191 OVreturn_word result;
3192 if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, mousemode))))
3193 return result;
3194 return OVOneToOne_GetForward(I->MouseModeLexicon, result.word);
3195 }
3196
PyMOL_ZoomScene(CPyMOL * I,float scale)3197 PyMOLreturn_status PyMOL_ZoomScene(CPyMOL * I, float scale){
3198 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
3199 PYMOL_API_LOCK
3200 SceneZoom(I->G, scale);
3201 PyMOL_NeedRedisplay(I);
3202 result.status = PyMOLstatus_SUCCESS;
3203 PYMOL_API_UNLOCK return result;
3204 }
3205
PyMOL_TranslateScene(CPyMOL * I,float x,float y,float z)3206 PyMOLreturn_status PyMOL_TranslateScene(CPyMOL * I, float x, float y, float z){
3207 PyMOLreturn_status result = { PyMOLstatus_FAILURE };
3208 PYMOL_API_LOCK
3209 SceneTranslate(I->G, x, y, z);
3210 result.status = PyMOLstatus_SUCCESS;
3211 PYMOL_API_UNLOCK return result;
3212 }
3213
3214 #include "palettes.h"
3215
get_palette(CPyMOL * I,char * palette)3216 static OVreturn_word get_palette(CPyMOL * I, char *palette)
3217 {
3218 OVreturn_word result;
3219 if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, palette))))
3220 return result;
3221 return OVOneToOne_GetForward(I->PaletteLexicon, result.word);
3222 }
3223
PyMOL_Spectrum(CPyMOL * I,const char * expression,const char * pal,const char * selection,float minimum,float maximum,int byres,int quiet)3224 PyMOLreturn_float_array PyMOL_Spectrum(CPyMOL * I, const char *expression, const char *pal, const char *selection, float minimum, float maximum, int byres, int quiet){
3225 PyMOLreturn_float_array result = { PyMOLstatus_FAILURE };
3226 PYMOL_API_LOCK
3227 int ok = true;
3228 int digits, first, last, array_pl, ret;
3229 float min_ret, max_ret;
3230 char prefix[2];
3231 OVreturn_word pal_word;
3232 char *palette = (char*)malloc(strlen(pal)+1);
3233 UtilNCopyToLower((char*)palette, pal, strlen(pal)+1);
3234
3235 if (ok)
3236 ok = OVreturn_IS_OK(pal_word = get_palette(I, (char*)palette));
3237 free(palette);
3238 prefix[0] = palette_prefix[pal_word.word];
3239 prefix[1] = 0;
3240 array_pl = pal_word.word * 3;
3241 digits = palette_data[array_pl++];
3242 first = palette_data[array_pl++];
3243 last = palette_data[array_pl++];
3244
3245 ret = ExecutiveSpectrum(I->G, selection, expression, minimum, maximum,
3246 first, last, prefix, digits, byres, quiet, &min_ret, &max_ret);
3247
3248 if (ret){
3249 result.size = 2;
3250 result.array = VLAlloc(float, 2);
3251 result.array[0] = min_ret;
3252 result.array[1] = max_ret;
3253 result.status = PyMOLstatus_SUCCESS;
3254 } else {
3255 result.status = PyMOLstatus_FAILURE;
3256 }
3257 PYMOL_API_UNLOCK return result;
3258 }
3259
3260 #endif
3261
PyMOL_GetVersion(CPyMOL * I)3262 PyMOLreturn_value PyMOL_GetVersion(CPyMOL * I){
3263 int ok = true;
3264 PyMOLreturn_value result;
3265 result.status = PyMOLstatus_FAILURE;
3266
3267 PYMOL_API_LOCK
3268 if(ok) {
3269 result.type = PYMOL_RETURN_VALUE_IS_STRING;
3270 result.string = mstrdup(_PyMOL_VERSION);
3271 result.status = PyMOLstatus_SUCCESS;
3272 };
3273 PYMOL_API_UNLOCK return result;
3274 }
3275
PyMOL_GetAtomPropertyInfo(CPyMOL * I,const char * atompropname)3276 AtomPropertyInfo *PyMOL_GetAtomPropertyInfo(CPyMOL * I, const char *atompropname)
3277 {
3278 OVreturn_word result;
3279 if(!OVreturn_IS_OK((result = OVLexicon_BorrowFromCString(I->Lex, atompropname))))
3280 return NULL;
3281 result = OVOneToOne_GetForward(I->AtomPropertyLexicon, result.word);
3282 if(!OVreturn_IS_OK(result))
3283 return NULL;
3284 return &I->AtomPropertyInfos[result.word];
3285 }
3286
3287 #ifdef __cplusplus
3288 }
3289 #endif
3290