1 
2 /*
3 A* -------------------------------------------------------------------
4 B* This file contains source code for the PyMOL computer program
5 C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
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 
19 #include"os_proprietary.h"
20 
21 #include"os_predef.h"
22 #include"os_std.h"
23 
24 #include"Base.h"
25 #include"OOMac.h"
26 #include"MemoryDebug.h"
27 #include"Ortho.h"
28 #include"Setting.h"
29 #include"Scene.h"
30 #include"ButMode.h"
31 #include"CGO.h"
32 #include"Executive.h"
33 #include"Editor.h"
34 #include"P.h"
35 #include"Util.h"
36 #include"main.h"
37 #include"PConv.h"
38 #include"Wizard.h"
39 #include"Seq.h"
40 #include"PyMOLOptions.h"
41 #include"OVContext.h"
42 #include"ShaderMgr.h"
43 #include"Sphere.h"
44 #include"Selector.h"
45 #include"Parse.h"
46 
47 #ifdef _PYMOL_OPENVR
48 #include"OpenVRMode.h"
49 #endif
50 
51 /*
52  * Setting level info table
53  *
54  * Levels are not hierarchical at the atom/bond level, that's why a simple
55  * sorted enumeration is not sufficient.
56  *
57  * global < object < object-state
58  *                   object-state < atom < atom-state
59  *                   object-state < bond < bond-state
60  */
61 const SettingLevelInfoType SettingLevelInfo[] = {
62   {"unused"        , 0x00}, // 0b00000000
63   {"global"        , 0x00}, // 0b00000000
64   {"object"        , 0x01}, // 0b00000001
65   {"object-state"  , 0x03}, // 0b00000011
66   {"atom"          , 0x07}, // 0b00000111
67   {"atom-state"    , 0x0F}, // 0b00001111
68   {"bond"          , 0x13}, // 0b00010011
69   {"bond-state"    , 0x33}, // 0b00110011
70   {NULL, 0}
71 };
72 
73 // The following defines the static SettingInfo table
74 #define SETTINGINFO_IMPLEMENTATION
75 #include "SettingInfo.h"
76 
77 template <> const char * SettingGet<const char *>(int index, const CSetting * I);
78 
79 // get level name for setting index (for feedback)
SettingLevelGetName(PyMOLGlobals * G,int index)80 const char * SettingLevelGetName(PyMOLGlobals * G, int index) {
81   return SettingLevelInfo[SettingInfo[index].level].name;
82 }
83 
84 // check if setting index is valid in given level-mask
SettingLevelCheckMask(PyMOLGlobals * G,int index,unsigned char mask)85 bool SettingLevelCheckMask(PyMOLGlobals * G, int index, unsigned char mask) {
86   unsigned char validmask = SettingLevelInfo[SettingInfo[index].level].mask;
87   return (0 == (mask & ~validmask));
88 }
89 
90 // check if setting index is valid in given level
SettingLevelCheck(PyMOLGlobals * G,int index,unsigned char level)91 bool SettingLevelCheck(PyMOLGlobals * G, int index, unsigned char level) {
92   return SettingLevelCheckMask(G, index, SettingLevelInfo[level].mask);
93 }
94 
95 /* ================================================================== */
96 
SettingCopyAll(PyMOLGlobals * G,const CSetting * src,CSetting * dst)97 static CSetting *SettingCopyAll(PyMOLGlobals * G, const CSetting * src, CSetting * dst)
98 {
99   if(!dst) {
100     dst = pymol::calloc<CSetting>(1);
101   } else {
102     SettingPurge(dst);
103   }
104 
105   SettingInit(G, dst);
106 
107   if(dst && src) {
108 
109     /* simply overwriting existing data (if any) ... in the future we
110        may need to release references etc. before doing this */
111 
112     unsigned int size = VLAGetSize(src->info);
113     VLACheck(dst->info, SettingRec, size - 1);
114     UtilCopyMem(dst->info, src->info, sizeof(SettingRec) * size);
115     dst->size = src->size;
116 
117     // need to properly copy strings
118     for (int index = 0; index < cSetting_INIT; ++index) {
119       if (SettingInfo[index].type == cSetting_string
120           && src->info[index].str_) {
121         dst->info[index].str_ = new std::string(*src->info[index].str_);
122       }
123     }
124   }
125   return dst;
126 }
127 
SettingStoreDefault(PyMOLGlobals * G)128 void SettingStoreDefault(PyMOLGlobals * G)
129 {
130   G->Default = SettingCopyAll(G, G->Setting, G->Default);
131 }
132 
SettingPurgeDefault(PyMOLGlobals * G)133 void SettingPurgeDefault(PyMOLGlobals * G)
134 {
135   if(G->Default) {
136     SettingPurge(G->Default);
137     FreeP(G->Default);
138     G->Default = NULL;
139   }
140 }
141 
SettingUniqueDetachChain(PyMOLGlobals * G,int unique_id)142 void SettingUniqueDetachChain(PyMOLGlobals * G, int unique_id)
143 {
144   CSettingUnique *I = G->SettingUnique;
145   OVreturn_word result;
146   if(OVreturn_IS_OK(result = OVOneToOne_GetForward(I->id2offset, unique_id))) {
147     int offset = result.word;
148     int next;
149 
150     OVOneToOne_DelForward(I->id2offset, unique_id);
151 
152     {
153       SettingUniqueEntry *entry;
154       while(offset) {
155         entry = I->entry + offset;
156         next = entry->next;
157         entry->next = I->next_free;
158         I->next_free = offset;
159         offset = next;
160       }
161     }
162   } else {
163     /* uncaught error */
164   }
165 }
166 
SettingUniqueExpand(PyMOLGlobals * G)167 static void SettingUniqueExpand(PyMOLGlobals * G)
168 {
169   CSettingUnique *I = G->SettingUnique;
170 
171   if(!I->next_free) {
172     int new_n_alloc = (I->n_alloc * 3) / 2;
173     int a;
174     VLACheck(I->entry, SettingUniqueEntry, new_n_alloc);
175     for(a = I->n_alloc; a < new_n_alloc; a++) {
176       I->entry[a].next = I->next_free;
177       I->next_free = a;
178     }
179     I->n_alloc = new_n_alloc;
180   }
181 }
182 
183 static
SettingFindSettingUniqueEntry(PyMOLGlobals * G,int unique_id,int setting_id)184 SettingUniqueEntry *SettingFindSettingUniqueEntry(PyMOLGlobals * G, int unique_id, int setting_id)
185 {
186   CSettingUnique *I = G->SettingUnique;
187   OVreturn_word result;
188   if(OVreturn_IS_OK(result = OVOneToOne_GetForward(I->id2offset, unique_id))) {
189     SettingUniqueEntry *entry;
190     for (int offset = result.word; offset; offset = entry->next) {
191       entry = I->entry + offset;
192       if(entry->setting_id == setting_id) {
193         return entry;
194       }
195     }
196   }
197   return NULL;
198 }
199 
SettingUniqueCheck(PyMOLGlobals * G,int unique_id,int setting_id)200 int SettingUniqueCheck(PyMOLGlobals * G, int unique_id, int setting_id)
201 {
202   return SettingFindSettingUniqueEntry(G, unique_id, setting_id) != NULL;
203 }
204 
205 /*
206  * Return true for convertible types and set int-compatible types to int
207  */
type_upcast(int & type)208 inline bool type_upcast(int &type) {
209   switch (type) {
210     case cSetting_int:
211     case cSetting_color:
212     case cSetting_boolean:
213       type = cSetting_int;
214     case cSetting_float:
215       return true;
216   }
217   return false;
218 }
219 
SettingUniqueGetTypedValuePtr(PyMOLGlobals * G,int unique_id,int setting_id,int setting_type,void * value)220 bool SettingUniqueGetTypedValuePtr(PyMOLGlobals * G, int unique_id, int setting_id,
221                                       int setting_type, void * value)
222 {
223   auto entry = SettingFindSettingUniqueEntry(G, unique_id, setting_id);
224   if (!entry)
225     return false;
226 
227   int type_from = SettingInfo[setting_id].type;
228 
229   if (type_from != setting_type) {
230     if (!type_upcast(type_from) ||
231         !type_upcast(setting_type)) {
232       PRINTFB(G, FB_Setting, FB_Errors)
233         " Setting-Error: type mismatch\n" ENDFB(G);
234       return false;
235     }
236   }
237 
238   if (setting_type == cSetting_float3){
239     *(const float **) value = entry->value.float3_;
240   } else if (setting_type == type_from) {
241     *(int *) value = entry->value.int_;
242   } else if (setting_type == cSetting_int) {
243     *(int *) value = (int) entry->value.float_;
244   } else { // setting_type == cSetting_float
245     *(float *) value = (float) entry->value.int_;
246   }
247 
248   return true;
249 }
250 
251 /*
252  * Warning: Returns colors as (fff) tuple instead of color index
253  */
SettingUniqueGetPyObject(PyMOLGlobals * G,int unique_id,int index)254 PyObject *SettingUniqueGetPyObject(PyMOLGlobals * G, int unique_id, int index)
255 {
256   int type = SettingGetType(G, index);
257 
258   union {
259     int val_i;
260     float val_f;
261     const float * ptr_3f;
262   };
263 
264   if (SettingUniqueGetTypedValuePtr(G, unique_id, index, type, &ptr_3f)) {
265     switch (type) {
266     case cSetting_boolean:
267       return CPythonVal_New_Boolean(val_i);
268     case cSetting_int:
269       return CPythonVal_New_Integer(val_i);
270     case cSetting_float:
271       return CPythonVal_New_Float(val_f);
272     case cSetting_color:
273 #ifdef _PYMOL_NOPY
274       return CPythonVal_New_Integer(val_i);
275 #else
276       return PYOBJECT_CALLFUNCTION(G->P_inst->colortype, "i", val_i);
277 #endif
278     case cSetting_float3:
279       {
280         PyObject *result = PyTuple_New(3);
281         PyTuple_SET_ITEM(result, 0, CPythonVal_New_Float(ptr_3f[0]));
282         PyTuple_SET_ITEM(result, 1, CPythonVal_New_Float(ptr_3f[1]));
283         PyTuple_SET_ITEM(result, 2, CPythonVal_New_Float(ptr_3f[2]));
284         return result;
285       }
286     }
287   }
288 
289   return NULL;
290 }
291 
SettingUniqueEntry_IsSame(SettingUniqueEntry * entry,int setting_type,const void * value)292 static int SettingUniqueEntry_IsSame(SettingUniqueEntry *entry, int setting_type, const void *value){
293   if (SettingInfo[entry->setting_id].type != setting_type){
294     return 0;
295   }
296   if (setting_type == cSetting_float3){
297     const float *v = (float*)value, *ev = entry->value.float3_;
298     return v[0]==ev[0] && v[1]==ev[1] && v[2]==ev[2];
299   } else {
300     return (entry->value.int_ == *(int *) value);
301   }
302 }
303 
SettingUniqueEntry_Set(SettingUniqueEntry * entry,int value_type,const void * value)304 static void SettingUniqueEntry_Set(SettingUniqueEntry *entry, int value_type, const void *value){
305   int setting_type = SettingGetType(entry->setting_id);
306   switch (value_type) {
307     case cSetting_boolean:
308     case cSetting_int:
309     case cSetting_color:
310       if (setting_type == cSetting_float) {
311         entry->value.float_ = *(int*) value;
312       } else {
313         entry->value.int_ = *(int *) value;
314       }
315       break;
316     case cSetting_float:
317       if (setting_type != cSetting_float) {
318         entry->value.int_ = *(float *) value;
319       } else {
320         entry->value.float_ = *(float *) value;
321       }
322       break;
323     case cSetting_float3:
324       memcpy(entry->value.float3_, *(const float **) value, sizeof(float) * 3);
325       break;
326     default:
327       printf("SettingUniqueEntry_Set-Error: unsupported type %d\n", value_type);
328   }
329 }
330 
331 /*
332  * Return false if setting was not set (nothing changed)
333  */
SettingUniqueUnset(PyMOLGlobals * G,int unique_id,int setting_id)334 bool SettingUniqueUnset(PyMOLGlobals * G, int unique_id, int setting_id)
335 {
336   auto I = G->SettingUnique;
337   auto result = OVOneToOne_GetForward(I->id2offset, unique_id);
338 
339   if (OVreturn_IS_OK(result)) {
340     for (int prev = 0, offset = result.word; offset;
341         prev = offset, offset = I->entry[offset].next) {
342       if (I->entry[offset].setting_id != setting_id)
343         continue;
344 
345       if(!prev) {           /* if first entry in list */
346         OVOneToOne_DelForward(I->id2offset, unique_id);
347         if(I->entry[offset].next) {   /* set new list start */
348           OVOneToOne_Set(I->id2offset, unique_id, I->entry[offset].next);
349         }
350       } else {              /* otherwise excise from middle or end */
351         I->entry[prev].next = I->entry[offset].next;
352       }
353       I->entry[offset].next = I->next_free;
354       I->next_free = offset;
355 
356       return true;
357     }
358   }
359   return false;
360 }
361 
SettingUniqueSetTypedValue(PyMOLGlobals * G,int unique_id,int setting_id,int setting_type,const void * value)362 int SettingUniqueSetTypedValue(PyMOLGlobals * G, int unique_id, int setting_id,
363 			       int setting_type, const void *value)
364 
365 /* set value to NULL in order to delete setting */
366 {
367   CSettingUnique *I = G->SettingUnique;
368   OVreturn_word result;
369   int isset = false;
370 
371   if (!value) {
372     return SettingUniqueUnset(G, unique_id, setting_id);
373   }
374 
375   if(OVreturn_IS_OK((result = OVOneToOne_GetForward(I->id2offset, unique_id)))) {       /* setting list exists for atom */
376     int offset = result.word;
377     int prev = 0;
378     int found = false;
379     while(offset) {
380       SettingUniqueEntry *entry = I->entry + offset;
381       if(entry->setting_id == setting_id) {
382         found = true;           /* this setting is already defined */
383 	  if (!SettingUniqueEntry_IsSame(entry, setting_type, value)){
384 	    SettingUniqueEntry_Set(entry, setting_type, value);
385 	    isset = true;
386 	  }
387         break;
388       }
389       prev = offset;
390       offset = entry->next;
391     }
392     if((!found) && value) {     /* setting not found in existing list, so append new value */
393       if(!I->next_free)
394         SettingUniqueExpand(G);
395       if(I->next_free) {
396         offset = I->next_free;
397         {
398           SettingUniqueEntry *entry = I->entry + offset;
399           I->next_free = entry->next;
400           entry->next = 0;
401 
402           if(prev) {            /* append onto existing list */
403             I->entry[prev].next = offset;
404             entry->setting_id = setting_id;
405             SettingUniqueEntry_Set(entry, setting_type, value);
406             isset = true;
407           } else if(OVreturn_IS_OK(OVOneToOne_Set(I->id2offset, unique_id, offset))) {
408             /* create new list */
409             entry->setting_id = setting_id;
410             SettingUniqueEntry_Set(entry, setting_type, value);
411             isset = true;
412           }
413         }
414       }
415     }
416   } else if(value && (result.status == OVstatus_NOT_FOUND)) {   /* new setting list for atom */
417     if(!I->next_free)
418       SettingUniqueExpand(G);
419     if(I->next_free) {
420       int offset = I->next_free;
421       SettingUniqueEntry *entry = I->entry + offset;
422 
423       if(OVreturn_IS_OK(OVOneToOne_Set(I->id2offset, unique_id, offset))) {
424         I->next_free = entry->next;
425         entry->setting_id = setting_id;
426         entry->next = 0;
427         SettingUniqueEntry_Set(entry, setting_type, value);
428         isset = true;
429       }
430     }
431   } else {
432     /* unhandled error */
433   }
434   return isset;
435 }
436 
437 #ifndef _PYMOL_NOPY
SettingUniqueSetPyObject(PyMOLGlobals * G,int unique_id,int index,PyObject * value)438 bool SettingUniqueSetPyObject(PyMOLGlobals * G, int unique_id, int index, PyObject *value)
439 {
440   if (!value)
441     return SettingUniqueUnset(G, unique_id, index);
442 
443   int type = SettingGetType(G, index);
444 
445   float val_3f[3];
446   union {
447     int val_i;
448     float val_f;
449     float * ptr_3f;
450   };
451 
452   switch (type) {
453   case cSetting_boolean:
454   case cSetting_int:
455     ok_assert(1, PConvPyObjectToInt(value, &val_i));
456     break;
457   case cSetting_float:
458     ok_assert(1, PConvPyObjectToFloat(value, &val_f));
459     break;
460   case cSetting_color:
461     if (!PConvPyIntToInt(value, &val_i)) {
462       OrthoLineType sval;
463       ok_assert(1, PConvPyStrToStr(value, sval, OrthoLineLength));
464       val_i = ColorGetIndex(G, sval);
465     }
466     break;
467   case cSetting_float3:
468     if (!PConvPyListOrTupleToFloatArrayInPlace(value, val_3f, 3)) {
469       OrthoLineType sval;
470       ok_assert(1, PConvPyStrToStr(value, sval, OrthoLineLength) &&
471           sscanf(sval, "%f%f%f", &val_3f[0], &val_3f[1], &val_3f[2]) == 3);
472     }
473     ptr_3f = val_3f;
474     break;
475   default:
476     PRINTFB(G, FB_Python, FB_Errors)
477       " Python-Error: atom-state-level setting unsupported type=%d\n", type ENDFB(G);
478     return false;
479   }
480 
481   return SettingUniqueSetTypedValue(G, unique_id, index, type, &val_i);
482 
483 ok_except1:
484   PRINTFB(G, FB_Setting, FB_Errors)
485     " Setting-Error: type mismatch\n" ENDFB(G);
486   return false;
487 }
488 #endif
489 
SettingUniqueResetAll(PyMOLGlobals * G)490 void SettingUniqueResetAll(PyMOLGlobals * G)
491 {
492   CSettingUnique *I = G->SettingUnique;
493 
494   OVOneToOne_Reset(I->id2offset);
495   {
496     int a;
497     I->n_alloc = 10;
498     VLAFreeP(I->entry);
499     I->entry = VLACalloc(SettingUniqueEntry, I->n_alloc);
500     /* note: intentially skip index 0  */
501     for(a = 2; a < 10; a++) {
502       I->entry[a].next = a - 1;
503     }
504     I->next_free = I->n_alloc - 1;
505   }
506 }
507 
SettingUniquePrintAll(PyMOLGlobals * G,int src_unique_id)508 int SettingUniquePrintAll(PyMOLGlobals * G, int src_unique_id)
509 {
510   int ok = true;
511   CSettingUnique *I = G->SettingUnique;
512   OVreturn_word src_result;
513   printf("SettingUniquePrintAll: ");
514   if(OVreturn_IS_OK(src_result = OVOneToOne_GetForward(I->id2offset, src_unique_id))) {
515     int src_offset = src_result.word;
516     SettingUniqueEntry *src_entry;
517     while(ok && src_offset) {
518       {
519 	src_entry = I->entry + src_offset;
520 	{
521 	  int setting_id = src_entry->setting_id;
522 	  int setting_type = SettingInfo[setting_id].type;
523 	  const char * setting_name = SettingInfo[setting_id].name;
524 	  switch (setting_type) {
525 	  case cSetting_int:
526 	  case cSetting_color:
527 	  case cSetting_boolean:
528 	    printf("%s:%d:%d:%d ", setting_name, setting_id, setting_type, src_entry->value.int_);
529 	    break;
530 	  case cSetting_float:
531 	    printf("%s:%d:%d:%f ", setting_name, setting_id, setting_type, src_entry->value.float_);
532 	    break;
533 	  case cSetting_float3:
534 	    printf("%s:%d:%d:%f,%f,%f ", setting_name, setting_id, setting_type, src_entry->value.float3_[0],
535 		   src_entry->value.float3_[1],
536 		   src_entry->value.float3_[2]);
537 	    break;
538 	  case cSetting_string:
539 	    printf("%s:%d:%d:s%d ", setting_name, setting_id, setting_type, src_entry->value.int_);
540 	    break;
541 	  }
542 	}
543       }
544       src_offset = I->entry[src_offset].next; /* src_entry invalid, since I->entry may have changed */
545     }
546   }
547   printf("\n");
548   return ok;
549 }
550 
SettingUniqueCopyAll(PyMOLGlobals * G,int src_unique_id,int dst_unique_id)551 int SettingUniqueCopyAll(PyMOLGlobals * G, int src_unique_id, int dst_unique_id)
552 {
553   int ok = true;
554   CSettingUnique *I = G->SettingUnique;
555   OVreturn_word dst_result;
556 
557   if(OVreturn_IS_OK((dst_result = OVOneToOne_GetForward(I->id2offset, dst_unique_id)))) {       /* setting list exists for atom */
558     PRINTFB(G, FB_Setting, FB_Errors)
559       " SettingUniqueCopyAll-Bug: merging settings not implemented\n"
560       ENDFB(G);
561     ok = false;
562   } else if(dst_result.status == OVstatus_NOT_FOUND) {  /* new setting list for atom */
563     OVreturn_word src_result;
564     if(OVreturn_IS_OK(src_result = OVOneToOne_GetForward(I->id2offset, src_unique_id))) {
565       int dst_offset = 0;
566       for (int src_offset = src_result.word; src_offset;
567           src_offset = I->entry[src_offset].next) {
568         SettingUniqueExpand(G); // this may reallocate I->entry
569 
570         if (!dst_offset) {
571           OVOneToOne_Set(I->id2offset, dst_unique_id, I->next_free);
572         } else {
573           I->entry[dst_offset].next = I->next_free;
574         }
575 
576         dst_offset = I->next_free;
577         I->next_free = I->entry[dst_offset].next;
578         I->entry[dst_offset] = I->entry[src_offset];
579         I->entry[dst_offset].next = 0;
580       }
581     }
582   } else {
583     ok = false;
584     /* unhandled error */
585   }
586 
587   return ok;
588 }
589 
SettingUniqueInit(PyMOLGlobals * G)590 static void SettingUniqueInit(PyMOLGlobals * G)
591 {
592   CSettingUnique *I = G->SettingUnique;
593 
594   if((I = (G->SettingUnique = pymol::calloc<CSettingUnique>(1)))) {
595     I->id2offset = OVOneToOne_New(G->Context->heap);
596     {
597       int a;
598       I->n_alloc = 10;
599       I->entry = VLACalloc(SettingUniqueEntry, I->n_alloc);
600       /* note: intentially skip index 0  */
601       for(a = 2; a < 10; a++) {
602         I->entry[a].next = a - 1;       /* 1-based linked list with 0 as sentinel */
603       }
604       I->next_free = I->n_alloc - 1;
605     }
606   }
607 }
608 
SettingUniqueFree(PyMOLGlobals * G)609 static void SettingUniqueFree(PyMOLGlobals * G)
610 {
611   CSettingUnique *I = G->SettingUnique;
612   VLAFreeP(I->entry);
613   OVOneToOne_Del(I->id2offset);
614   FreeP(I);
615 }
616 
617 /*
618  * For unique_id remapping during partial session loading
619  */
SettingUniqueConvertOldSessionID(PyMOLGlobals * G,int old_unique_id)620 int SettingUniqueConvertOldSessionID(PyMOLGlobals * G, int old_unique_id)
621 {
622   CSettingUnique *I = G->SettingUnique;
623   int unique_id = old_unique_id;
624   if(I->old2new) {
625     OVreturn_word ret;
626     if(OVreturn_IS_OK(ret = OVOneToOne_GetForward(I->old2new, old_unique_id))) {
627       unique_id = ret.word;
628     } else {
629       unique_id = AtomInfoGetNewUniqueID(G);
630       OVOneToOne_Set(I->old2new, old_unique_id, unique_id);
631     }
632   } else {
633     AtomInfoReserveUniqueID(G, unique_id);
634   }
635   return unique_id;
636 }
637 
638 /*
639  * Return true if the given setting index should not be stored to PSE.
640  *
641  * Blacklisted are unused and system-dependent settings.
642  */
is_session_blacklisted(int index)643 static bool is_session_blacklisted(int index) {
644   if (index >= cSetting_INIT ||
645       SettingInfo[index].level == cSettingLevel_unused) {
646     return true;
647   }
648 
649   switch (index) {
650   case cSetting_antialias_shader:
651   case cSetting_ati_bugs:
652   case cSetting_cache_max:
653   case cSetting_cgo_shader_ub_color:
654   case cSetting_cgo_shader_ub_flags:
655   case cSetting_cgo_shader_ub_normal:
656   case cSetting_colored_feedback:
657   case cSetting_cylinder_shader_ff_workaround:
658   case cSetting_defer_updates:
659   case cSetting_fast_idle:
660   case cSetting_internal_feedback:
661   case cSetting_internal_gui:
662   case cSetting_internal_prompt:
663   case cSetting_logging:
664   case cSetting_max_threads:
665   case cSetting_mouse_grid:
666   case cSetting_mouse_scale:
667   case cSetting_nb_spheres_use_shader:
668   case cSetting_no_idle:
669   case cSetting_nvidia_bugs:
670   case cSetting_presentation:
671   case cSetting_precomputed_lighting:
672   case cSetting_render_as_cylinders:
673   case cSetting_security:
674   case cSetting_session_changed:
675   case cSetting_session_file:
676   case cSetting_session_migration:
677   case cSetting_session_version_check:
678   case cSetting_shaders_from_disk:
679   case cSetting_show_progress:
680   case cSetting_slow_idle:
681   case cSetting_stereo:
682   case cSetting_stereo_double_pump_mono:
683   case cSetting_stereo_mode:
684   case cSetting_suspend_deferred:
685   case cSetting_suspend_undo:
686   case cSetting_suspend_undo_atom_count:
687   case cSetting_suspend_updates:
688   case cSetting_text:
689   case cSetting_trilines:
690   case cSetting_use_geometry_shaders:
691   case cSetting_use_shaders:
692   case cSetting_pick32bit:
693   case cSetting_display_scale_factor:
694 #ifdef _PYMOL_IOS
695   case cSetting_cgo_sphere_quality:
696   case cSetting_dynamic_measures:
697   case cSetting_label_outline_color:
698   case cSetting_mouse_selection_mode:
699   case cSetting_sphere_mode:
700   case cSetting_sphere_quality:
701   case cSetting_stick_ball:
702   case cSetting_virtual_trackball:
703 #elif defined(_PYMOL_ACTIVEX)
704   case cSetting_async_builds:
705 #endif
706     return true;
707   }
708 
709   return false;
710 }
711 
SettingUniqueFromPyList(PyMOLGlobals * G,PyObject * list,int partial_restore)712 int SettingUniqueFromPyList(PyMOLGlobals * G, PyObject * list, int partial_restore)
713 {
714   int ok = true;
715   if(!partial_restore) {
716     SettingUniqueResetAll(G);
717   }
718   if(list)
719     if(PyList_Check(list)) {
720       ov_size n_id = PyList_Size(list);
721       ov_size a;
722       for(a = 0; a < n_id; a++) {
723         PyObject *id_list = PyList_GetItem(list, a);
724         int unique_id;
725         if(ok)
726           ok = PyList_Check(id_list);
727         if(ok)
728           ok = (PyList_Size(id_list) > 1);
729         if(ok)
730           ok = PConvPyIntToInt(PyList_GetItem(id_list, 0), &unique_id);
731         if(ok && partial_restore) {
732           unique_id = SettingUniqueConvertOldSessionID(G, unique_id);
733         }
734         if(ok) {
735           ov_size n_set = 0;
736 
737           PyObject *setting_list = PyList_GetItem(id_list, 1);
738           if(ok)
739             ok = PyList_Check(setting_list);
740           if(ok)
741             n_set = PyList_Size(setting_list);
742           if(ok) {
743             ov_size b;
744             for(b = 0; b < n_set; b++) {
745               PyObject *entry_list = PyList_GetItem(setting_list, b);
746               if(ok)
747                 ok = PyList_Check(entry_list);
748               if(ok)
749                 ok = (PyList_Size(entry_list) > 2);
750               if(ok) {
751                 int setting_id;
752                 int setting_type;
753                 float val_3f[3];
754                 union {
755                   int int_;
756                   float float_;
757 		  float * float3_;
758                 } value_store;
759                 if(ok)
760                   ok = PConvPyIntToInt(PyList_GetItem(entry_list, 0), &setting_id);
761                 if(ok)
762                   ok = PConvPyIntToInt(PyList_GetItem(entry_list, 1), &setting_type);
763                 if(ok)
764                   switch (setting_type) {
765 
766                   case cSetting_int:
767                   case cSetting_color:
768                   case cSetting_boolean:
769                     ok = PConvPyIntToInt(PyList_GetItem(entry_list, 2),
770                                          &value_store.int_);
771                     break;
772                   case cSetting_float:
773                     ok = PConvPyFloatToFloat(PyList_GetItem(entry_list, 2),
774                                              &value_store.float_);
775                     break;
776 		  case cSetting_float3:
777 		    {
778 		      CPythonVal *el = CPythonVal_PyList_GetItem(G, entry_list, 2);
779 		      value_store.float3_ = val_3f;
780 		      ok = PConvPyListToFloatArrayInPlace(el, value_store.float3_, 3);
781 		      CPythonVal_Free(el);
782 		    }
783 		    break;
784                   }
785                 if(ok) {
786                   SettingUniqueSetTypedValue(G, unique_id, setting_id,
787                                              setting_type, &value_store);
788                 }
789               }
790             }
791           }
792         }
793       }
794     }
795   return ok;
796 }
797 
SettingUniqueAsPyList(PyMOLGlobals * G)798 PyObject *SettingUniqueAsPyList(PyMOLGlobals * G)
799 {
800   PyObject *result = NULL;
801   CSettingUnique *I = G->SettingUnique;
802   {
803     ov_word hidden = 0;
804     OVreturn_word ret;
805     int n_entry = 0;
806     while(1) {
807       ret = OVOneToOne_IterateForward(I->id2offset, &hidden);
808       if(ret.status != OVstatus_YES)
809         break;
810       n_entry++;
811     }
812     result = PyList_New(n_entry);
813     if(result) {
814       hidden = 0;
815       n_entry = 0;
816       while(1) {
817         PyObject *setting_list = NULL;
818         int save_offset, unique_id;
819         ret = OVOneToOne_IterateForward(I->id2offset, &hidden);
820 
821         if(ret.status != OVstatus_YES)
822           break;
823         unique_id = ret.word;
824         if(OVreturn_IS_OK(ret = OVOneToOne_GetForward(I->id2offset, unique_id))) {
825           int offset = ret.word;
826           int n_set = 0;
827 
828           /* count number of settings for this unique_id */
829 
830           SettingUniqueEntry *entry;
831           save_offset = offset;
832           while(offset) {
833             entry = I->entry + offset;
834             n_set++;
835             offset = entry->next;
836           }
837 
838           /* create and insert list for each setting */
839 
840           setting_list = PyList_New(n_set);
841           n_set = 0;
842           offset = save_offset;
843           while(offset) {
844             PyObject *setting_entry = PyList_New(3);
845             entry = I->entry + offset;
846             int type = SettingInfo[entry->setting_id].type;
847             PyList_SetItem(setting_entry, 0, PyInt_FromLong(entry->setting_id));
848             PyList_SetItem(setting_entry, 1, PyInt_FromLong(type));
849             switch (type) {
850             case cSetting_int:
851             case cSetting_color:
852             case cSetting_boolean:
853               PyList_SetItem(setting_entry, 2, PyInt_FromLong(entry->value.int_));
854               break;
855             case cSetting_float:
856               PyList_SetItem(setting_entry, 2,
857                              PyFloat_FromDouble(*(float *) &entry->value.float_));
858               break;
859 	    case cSetting_float3:
860 	      PyList_SetItem(setting_entry, 2,
861 			     PConvFloatArrayToPyList((float *) &entry->value.float3_, 3));
862 	      break;
863             }
864             PyList_SetItem(setting_list, n_set, setting_entry);
865             n_set++;
866             offset = entry->next;
867           }
868         }
869 
870         /* add this unique_id set into the overall list */
871 
872         {
873           PyObject *unique_list = PyList_New(2);
874           PyList_SetItem(unique_list, 0, PyInt_FromLong(unique_id));
875           PyList_SetItem(unique_list, 1, setting_list);
876           PyList_SetItem(result, n_entry, unique_list);
877         }
878         n_entry++;
879       }
880     }
881   }
882   return (PConvAutoNone(result));
883 }
884 
SettingSetSmart_i(PyMOLGlobals * G,CSetting * set1,CSetting * set2,int index,int value)885 int SettingSetSmart_i(PyMOLGlobals * G, CSetting * set1, CSetting * set2, int index,
886                       int value)
887 {
888   int dummy;
889   if(set1 && SettingGetIfDefined_i(G, set1, index, &dummy)) {
890     return SettingSet_i(set1, index, value);
891   }
892   if(set2 && SettingGetIfDefined_i(G, set2, index, &dummy)) {
893     return SettingSet_i(set2, index, value);
894   }
895   return SettingSetGlobal_i(G, index, value);
896 }
897 
SettingSetGlobalsFromPyList(PyMOLGlobals * G,PyObject * list)898 int SettingSetGlobalsFromPyList(PyMOLGlobals * G, PyObject * list)
899 {
900   int ok = true;
901 
902   CSetting *I = G->Setting;
903 
904   if(list)
905     if(PyList_Check(list))
906       ok = SettingFromPyList(I, list);
907 
908   /* restore the following settings  */
909 
910   if(G->Option->no_quit) {
911     SettingSet_b(I, cSetting_presentation_auto_quit, 0);
912   }
913 
914   ColorUpdateFrontFromSettings(G);
915   return (ok);
916 }
917 
SettingGetGlobalsAsPyList(PyMOLGlobals * G)918 PyObject *SettingGetGlobalsAsPyList(PyMOLGlobals * G)
919 {
920   PyObject *result = NULL;
921   CSetting *I = G->Setting;
922   result = SettingAsPyList(I);
923   return (PConvAutoNone(result));
924 }
925 
get_list(CSetting * I,int index,bool incl_blacklisted)926 static PyObject *get_list(CSetting * I, int index, bool incl_blacklisted)
927 {
928   PyObject *result = NULL, *value = NULL;
929   int setting_type = SettingInfo[index].type;
930 
931   if (!incl_blacklisted && is_session_blacklisted(index)) {
932     return NULL;
933   }
934 
935   switch (setting_type) {
936 
937   case cSetting_boolean:
938   case cSetting_int:
939   case cSetting_color:
940     value = PyInt_FromLong(I->info[index].int_);
941     break;
942   case cSetting_float:
943     value = PyFloat_FromDouble(I->info[index].float_);
944     break;
945   case cSetting_float3:
946     value = PConvFloatArrayToPyList(I->info[index].float3_, 3);
947     break;
948   case cSetting_string:
949     value = PyString_FromString(SettingGet<const char *>(index, I));
950     break;
951   }
952 
953   if (value) {
954     result = PyList_New(3);
955     PyList_SetItem(result, 0, PyInt_FromLong(index));
956     PyList_SetItem(result, 1, PyInt_FromLong(setting_type));
957     PyList_SetItem(result, 2, value);
958   }
959 
960   return result;
961 }
962 
SettingAsPyList(CSetting * I,bool incl_blacklisted)963 PyObject *SettingAsPyList(CSetting * I, bool incl_blacklisted)
964 {
965   PyObject *result = NULL;
966   int a;
967 
968   if(I) {
969     std::vector<PyObject*> list;
970     list.reserve(cSetting_INIT);
971 
972     for(a = 0; a < cSetting_INIT; a++) {
973       if(I->info[a].defined) {
974         PyObject * item = get_list(I, a, incl_blacklisted);
975         if (item != NULL) {
976           list.push_back(item);
977         }
978       }
979     }
980 
981     result = PConvToPyObject(list);
982   }
983   return (PConvAutoNone(result));
984 }
985 
986 /*========================================================================*/
SettingCheckUseShaders(CSetting * I,int quiet)987 static int SettingCheckUseShaders(CSetting * I, int quiet)
988 {
989   PyMOLGlobals * G = I->G;
990     if (SettingGetGlobal_i(G, cSetting_use_shaders)){
991       if (G->ShaderMgr->IsConfigured() && !G->ShaderMgr->ShadersPresent()){
992 	SettingSet_b(I, cSetting_use_shaders, 0);
993 	if (!quiet){
994 	  PRINTFB(G, FB_Setting, FB_Warnings)
995 	    "Setting-Error: use_shaders cannot be set when Shaders are not available, setting use_shaders back to false\n"
996 	    ENDFB(G);
997 	}
998 	return 1;
999       }
1000     }
1001     return 0;
1002 }
1003 
1004 /*========================================================================*/
set_list(CSetting * I,PyObject * list)1005 static int set_list(CSetting * I, PyObject * list)
1006 {
1007   int index = -1;
1008   int setting_type = -1;
1009 
1010   union {
1011     int val_i;
1012     float val_f;
1013     float val_3f[3];
1014     const char * val_s;
1015   };
1016 
1017   if (list == NULL || CPythonVal_IsNone(list))
1018     return true;
1019 
1020   ok_assert(1, PyList_Check(list));
1021   ok_assert(1, CPythonVal_PConvPyIntToInt_From_List(I->G, list, 0, &index));
1022   ok_assert(1, CPythonVal_PConvPyIntToInt_From_List(I->G, list, 1, &setting_type));
1023 
1024   if (is_session_blacklisted(index))
1025     return true;
1026 
1027   switch (setting_type) {
1028   case cSetting_boolean:
1029   case cSetting_int:
1030   case cSetting_color:
1031     ok_assert(1, CPythonVal_PConvPyIntToInt_From_List(I->G, list, 2, &val_i));
1032     if (setting_type == cSetting_color)
1033       val_i = ColorConvertOldSessionIndex(I->G, val_i);
1034     SettingSet_i(I, index, val_i);
1035     break;
1036   case cSetting_float:
1037     ok_assert(1, CPythonVal_PConvPyFloatToFloat_From_List(I->G, list, 2, &val_f));
1038     SettingSet_f(I, index, val_f);
1039     break;
1040   case cSetting_float3:
1041     ok_assert(1, CPythonVal_PConvPyListToFloatArrayInPlaceAutoZero_From_List(I->G, list, 2, val_3f, 3));
1042     SettingSet_3fv(I, index, val_3f);
1043     break;
1044   case cSetting_string:
1045     ok_assert(1, val_s = PyString_AsString(PyList_GetItem(list, 2)));
1046     SettingSet_s(I, index, val_s);
1047     break;
1048   default:
1049     ok_raise(1);
1050   }
1051 
1052   return true;
1053 ok_except1:
1054   printf(" set_list-Error: i=%d, t=%d\n", index, setting_type);
1055   return false;
1056 }
1057 
1058 /*========================================================================*/
1059 /*
1060  * Used to set object and object-state level settings from PSEs
1061  */
SettingNewFromPyList(PyMOLGlobals * G,PyObject * list)1062 CSetting *SettingNewFromPyList(PyMOLGlobals * G, PyObject * list)
1063 {
1064   int ok = true;
1065   ov_size size;
1066   ov_size a;
1067   CSetting *I = NULL;
1068   if(ok)
1069     ok = (list != NULL);
1070   if(ok)
1071     ok = PyList_Check(list);
1072   if(ok) {
1073     I = SettingNew(G);
1074     size = PyList_Size(list);
1075     for(a = 0; a < size; a++) {
1076       if(ok)
1077         ok = set_list(I, PyList_GetItem(list, a));
1078     }
1079   }
1080   return (I);
1081 }
1082 
1083 /*========================================================================*/
SettingFromPyList(CSetting * I,PyObject * list)1084 int SettingFromPyList(CSetting * I, PyObject * list)
1085 {
1086   int ok = true;
1087   ov_size size;
1088   ov_size a;
1089 
1090   if(ok)
1091     ok = (I != NULL);
1092   if(ok)
1093     ok = PyList_Check(list);
1094   if(ok) {
1095     size = PyList_Size(list);
1096     for(a = 0; a < size; a++) {
1097       if(!set_list(I, PyList_GetItem(list, a)))
1098         ok = false;
1099     }
1100   }
1101   return (ok);
1102 }
1103 
1104 /*========================================================================*/
1105 /*
1106  * Get the indices of all settings that have changed since last calling
1107  * this function. Resets the "changed" flag.
1108  *
1109  * NOTE: assumes blocked interpreter
1110  *
1111  * name: object name or NULL/"" for global settings
1112  * state: object state
1113  */
SettingGetUpdateList(PyMOLGlobals * G,const char * name,int state)1114 std::vector<int> SettingGetUpdateList(PyMOLGlobals * G, const char * name, int state)
1115 {
1116   CSetting **handle, *I = G->Setting;
1117   int a;
1118   int n;
1119   std::vector<int> result;
1120 
1121   if (name && name[0]) {
1122     // object-state settings
1123 
1124     CObject *obj = ExecutiveFindObjectByName(G, name);
1125 
1126     if (!obj ||
1127         !(handle = obj->getSettingHandle(state)) ||
1128         !(I = *handle))
1129       // not found -> empty list
1130       return result;
1131   }
1132 
1133   n = VLAGetSize(I->info);
1134   for(a = 0; a < n; a++) {
1135     if(I->info[a].changed) {
1136       I->info[a].changed = false;
1137       result.push_back(a);
1138     }
1139   }
1140   return (result);
1141 
1142 }
1143 
1144 
1145 /*========================================================================*/
SettingCheckHandle(PyMOLGlobals * G,CSetting ** handle)1146 void SettingCheckHandle(PyMOLGlobals * G, CSetting ** handle)
1147 {
1148   if(!*handle)
1149     *handle = SettingNew(G);
1150 }
1151 
1152 
1153 /*========================================================================*/
SettingGetTextValue(PyMOLGlobals * G,const CSetting * set1,const CSetting * set2,int index,char * buffer)1154 int SettingGetTextValue(PyMOLGlobals * G, const CSetting * set1, const CSetting * set2, int index,
1155                         char *buffer)
1156 {
1157   const char * sptr = SettingGetTextPtr(G, set1, set2, index, buffer);
1158   if(!sptr)
1159     return 0;
1160 
1161   if (sptr != buffer) {
1162     if(strlen(sptr) > OrthoLineLength) {
1163       PRINTFB(G, FB_Setting, FB_Warnings)
1164         "Setting-Warning: text longer than OrthoLineLength" ENDFB(G);
1165     }
1166 
1167     strncpy(buffer, sptr, OrthoLineLength);
1168   }
1169 
1170   return 1;
1171 }
1172 
1173 /*========================================================================*/
1174 /*
1175  * Returns a pointer to the internal string representation if available,
1176  * or it formats the value into buffer and returns a pointer to buffer.
1177  */
SettingGetTextPtr(PyMOLGlobals * G,const CSetting * set1,const CSetting * set2,int index,char * buffer)1178 const char * SettingGetTextPtr(PyMOLGlobals * G, const CSetting * set1, const CSetting * set2,
1179                                int index, char *buffer)
1180 {
1181   int type;
1182   const char *sptr = NULL;
1183   const float *ptr;
1184   type = SettingGetType(G, index);
1185   switch (type) {
1186   case cSetting_boolean:
1187     sprintf(buffer, SettingGet_b(G, set1, set2, index) ? "on" : "off");
1188     break;
1189   case cSetting_int:
1190     sprintf(buffer, "%d", SettingGet_i(G, set1, set2, index));
1191     break;
1192   case cSetting_float:
1193     sprintf(buffer, "%1.5f", SettingGet_f(G, set1, set2, index));
1194     break;
1195   case cSetting_float3:
1196     ptr = SettingGet_3fv(G, set1, set2, index);
1197     sprintf(buffer, "[ %1.5f, %1.5f, %1.5f ]", ptr[0], ptr[1], ptr[2]);
1198     break;
1199   case cSetting_color:
1200     {
1201       int color = SettingGet_color(G, set1, set2, index);
1202       switch (color) {
1203         case cColorAtomic:
1204           strcpy(buffer, "atomic");
1205           break;
1206         case cColorObject:
1207           strcpy(buffer, "object");
1208           break;
1209         case cColorFront:
1210           strcpy(buffer, "front");
1211           break;
1212         case cColorBack:
1213           strcpy(buffer, "back");
1214           break;
1215         case -1:
1216           strcpy(buffer, "default");
1217           break;
1218         default:
1219           sptr = ColorGetName(G, color);
1220           if(sptr)
1221             return sptr;
1222               strcpy(buffer, "invalid");
1223       }
1224     }
1225     break;
1226   case cSetting_string:
1227     return SettingGet_s(G, set1, set2, index);
1228   default:
1229     return NULL;
1230   }
1231   return buffer;
1232 }
1233 
1234 
1235 #ifndef _PYMOL_NOPY
1236 /*========================================================================*/
SettingSetFromTuple(PyMOLGlobals * G,CSetting * I,int index,PyObject * tuple)1237 int SettingSetFromTuple(PyMOLGlobals * G, CSetting * I, int index, PyObject * tuple)
1238 /* must have interpret locked to make this call */
1239 {
1240   PyObject *value;
1241   int type;
1242   int ok = true;
1243   if(!I)
1244     I = G->Setting;             /* fall back on global settings */
1245 
1246   /* this data structure has been pre-checked at the python level... */
1247 
1248   type = PyInt_AsLong(PyTuple_GetItem(tuple, 0));
1249   value = PyTuple_GetItem(tuple, 1);
1250   switch (type) {
1251   case cSetting_boolean:
1252   case cSetting_int:
1253     SettingSet_i(I, index, PyInt_AsLong(value));
1254     break;
1255   case cSetting_float:
1256     SettingSet_f(I, index, (float) PyFloat_AsDouble(value));
1257     break;
1258   case cSetting_float3:
1259     float tmp[3];
1260     PyArg_ParseTuple(value, "fff", tmp, tmp + 1, tmp + 2);
1261     SettingSet_3fv(I, index, tmp);
1262     break;
1263   case cSetting_color:
1264     SettingSet_color(I, index, PyString_AsString(value));
1265     break;
1266   case cSetting_string:
1267     SettingSet_s(I, index, PyString_AsString(value));
1268     break;
1269   default:
1270     ok = false;
1271     break;
1272   }
1273   return (ok);
1274 }
1275 #endif
1276 
1277 /*========================================================================*/
SettingStringToTypedValue(PyMOLGlobals * G,int index,const char * st,int * type,int * value)1278 int SettingStringToTypedValue(PyMOLGlobals * G, int index, const char *st, int *type,
1279                               int *value)
1280 {
1281   int ok = true;
1282   int newvalue ;
1283   float newfvalue;
1284   /* this data structure has been pre-checked at the python level... */
1285 
1286   *type = SettingGetType(G, index);
1287 
1288   switch (*type) {
1289   case cSetting_boolean:
1290     if((!*st) || (*st == '0') || (*st == 'F') || WordMatchExact(G, st, "on", true)
1291        || WordMatchExact(G, st, "false", true)){
1292           newvalue = 0;
1293       } else {
1294           newvalue = 1;
1295       }
1296       if (newvalue != *value){
1297           *value = newvalue;
1298       } else {
1299           ok = false;
1300       }
1301     break;
1302   case cSetting_int:
1303     if(sscanf(st, "%d", &newvalue) != 1){
1304         ok = false;
1305     } else if (newvalue!=*value){
1306         *value = newvalue;
1307     } else {
1308         ok = false;
1309     }
1310     break;
1311   case cSetting_float:
1312     if(sscanf(st, "%f", &newfvalue) != 1){
1313         ok = false;
1314     } else if (newfvalue != *((float *) value)){
1315         *(float*)value = newfvalue;
1316     } else {
1317         ok = false;
1318     }
1319     break;
1320   case cSetting_color:
1321     {
1322       int color_index = ColorGetIndex(G, st);
1323       if (*(value) != color_index){
1324           *(value) = color_index;
1325       } else {
1326           ok = false;
1327       }
1328     }
1329     break;
1330   default:
1331     ok = false;
1332     break;
1333   }
1334   return (ok);
1335 }
1336 
SettingSetFromString(PyMOLGlobals * G,CSetting * I,int index,const char * st)1337 int SettingSetFromString(PyMOLGlobals * G, CSetting * I, int index, const char *st)
1338 {
1339   int type;
1340   int ok = true;
1341   if(!I)
1342     I = G->Setting;             /* fall back on global settings */
1343 
1344   /* this data structure has been pre-checked at the python level... */
1345 
1346   type = SettingGetType(G, index);
1347 
1348   switch (type) {
1349   case cSetting_boolean:
1350     if((!*st) || (*st == '0') || (*st == 'F') || WordMatchExact(G, st, "on", true)
1351        || WordMatchExact(G, st, "false", true))
1352       SettingSet_b(I, index, 0);
1353     else
1354       SettingSet_b(I, index, 1);
1355     break;
1356   case cSetting_int:
1357     {
1358       int tmp;
1359       if(sscanf(st, "%d", &tmp) == 1)
1360         SettingSet_i(I, index, tmp);
1361       else
1362         ok = false;
1363     }
1364     break;
1365   case cSetting_float:
1366     {
1367       float tmp;
1368       if(sscanf(st, "%f", &tmp) == 1)
1369         SettingSet_f(I, index, tmp);
1370       else
1371         ok = false;
1372     }
1373     break;
1374   case cSetting_float3:
1375     {
1376       float tmp[3];
1377       if(sscanf(st, "%f%f%f", tmp, tmp + 1, tmp + 2) == 3)
1378         SettingSet_3fv(I, index, tmp);
1379       else
1380         ok = false;
1381     }
1382     break;
1383   case cSetting_color:
1384     SettingSet_color(I, index, st);
1385     break;
1386   case cSetting_string:
1387     SettingSet_s(I, index, st);
1388     break;
1389   default:
1390     ok = false;
1391     break;
1392   }
1393   return (ok);
1394 }
1395 
1396 
1397 /*========================================================================*/
1398 #ifndef _PYMOL_NOPY
1399 /*
1400  * Warning: Returns colors as (fff) tuple instead of color index
1401  */
SettingGetPyObject(PyMOLGlobals * G,const CSetting * set1,const CSetting * set2,int index)1402 PyObject *SettingGetPyObject(PyMOLGlobals * G, const CSetting * set1, const CSetting * set2, int index)
1403 {                               /* assumes blocked python interpeter */
1404   PyObject *result = NULL;
1405   const float *ptr;
1406   int type = SettingGetType(G, index);
1407 
1408   switch (type) {
1409   case cSetting_boolean:
1410     result = CPythonVal_New_Boolean(SettingGet_b(G, set1, set2, index));
1411     break;
1412   case cSetting_int:
1413     result = CPythonVal_New_Integer(SettingGet_i(G, set1, set2, index));
1414     break;
1415   case cSetting_float:
1416     result = CPythonVal_New_Float(SettingGet_f(G, set1, set2, index));
1417     break;
1418   case cSetting_float3:
1419     ptr = SettingGet_3fv(G, set1, set2, index);
1420     result = Py_BuildValue("(fff)", pymol::pretty_f2d(ptr[0]),
1421         pymol::pretty_f2d(ptr[1]), pymol::pretty_f2d(ptr[2]));
1422     break;
1423   case cSetting_color:
1424     {
1425       int retcol = SettingGet_color(G, set1, set2, index);
1426       if (retcol > 0){
1427 	const float *col;
1428 	col = ColorGet(G, retcol);
1429 	result = Py_BuildValue("(fff)", col[0], col[1], col[2]);
1430       }
1431     }
1432     break;
1433   case cSetting_string:
1434     result = PyString_FromString(SettingGet_s(G, set1, set2, index));
1435     break;
1436   }
1437   return result;
1438 }
1439 
SettingGetTuple(PyMOLGlobals * G,const CSetting * set1,const CSetting * set2,int index)1440 PyObject *SettingGetTuple(PyMOLGlobals * G, const CSetting * set1, const CSetting * set2, int index)
1441 {                               /* assumes blocked python interpeter */
1442   PyObject *result = NULL;
1443   const float *ptr;
1444   int type = SettingGetType(G, index);
1445 
1446   switch (type) {
1447   case cSetting_boolean:
1448   case cSetting_int:
1449   case cSetting_color:
1450     result = Py_BuildValue("ii", type, SettingGet_i(G, set1, set2, index));
1451     break;
1452   case cSetting_float:
1453     result = Py_BuildValue(
1454         "if", type, pymol::pretty_f2d(SettingGet_f(G, set1, set2, index)));
1455     break;
1456   case cSetting_float3:
1457     ptr = SettingGet_3fv(G, set1, set2, index);
1458     result = Py_BuildValue("i(fff)", type, pymol::pretty_f2d(ptr[0]),
1459         pymol::pretty_f2d(ptr[1]), pymol::pretty_f2d(ptr[2]));
1460     break;
1461   case cSetting_string:
1462     result = Py_BuildValue("is", type, SettingGet_s(G, set1, set2, index));
1463     break;
1464   default:
1465     result = PConvAutoNone(Py_None);
1466     break;
1467   }
1468   return result;
1469 }
1470 #endif
1471 
1472 
1473 /*========================================================================*/
SettingNew(PyMOLGlobals * G)1474 CSetting *SettingNew(PyMOLGlobals * G)
1475 {
1476   OOAlloc(G, CSetting);
1477   SettingInit(G, I);
1478   return (I);
1479 }
1480 
1481 
1482 /*========================================================================*/
SettingPurge(CSetting * I)1483 void SettingPurge(CSetting * I)
1484 {
1485   if(I) {
1486     // need to free strings
1487     for(int index = 0; index < cSetting_INIT; ++index) {
1488       if (SettingInfo[index].type == cSetting_string) {
1489         I->info[index].delete_s();
1490       }
1491     }
1492 
1493     VLAFreeP(I->info);
1494     I->size = 0;
1495   }
1496 }
1497 
1498 
1499 /*========================================================================*/
SettingFreeP(CSetting * I)1500 void SettingFreeP(CSetting * I)
1501 {
1502   if(I)
1503     SettingPurge(I);
1504   OOFreeP(I);
1505 }
1506 
1507 
1508 /*========================================================================*/
SettingInit(PyMOLGlobals * G,CSetting * I)1509 void SettingInit(PyMOLGlobals * G, CSetting * I)
1510 {
1511   I->G = G;
1512   I->size = sizeof(int);        /* insures offset is never zero, except when undef */
1513   I->info = (SettingRec*) VLAMalloc(cSetting_INIT, sizeof(SettingRec), 5, 1); /* auto-zero */
1514 }
1515 
1516 
1517 /*========================================================================*/
1518 /*
1519  * Return false if type is numeric and default value is non-zero.
1520  */
SettingIsDefaultZero(int index)1521 bool SettingIsDefaultZero(int index)
1522 {
1523   switch (SettingInfo[index].type) {
1524     case cSetting_boolean:
1525     case cSetting_int:
1526     case cSetting_float:
1527       if (SettingInfo[index].value.i[0] == 0)
1528         return true;
1529       return false;
1530   }
1531 
1532   return true;
1533 }
1534 
1535 
1536 /*========================================================================*/
1537 /*
1538  * Restore the default value from `src` or `SettingInfo`
1539  */
SettingRestoreDefault(CSetting * I,int index,const CSetting * src)1540 void SettingRestoreDefault(CSetting * I, int index, const CSetting * src)
1541 {
1542   // 1) from stored default if provided
1543   if (src) {
1544     UtilCopyMem(I->info + index, src->info + index, sizeof(SettingRec));
1545 
1546     // need to properly copy strings
1547     if (SettingInfo[index].type == cSetting_string && src->info[index].str_) {
1548       I->info[index].str_ = new std::string(*src->info[index].str_);
1549     }
1550 
1551     return;
1552   }
1553 
1554   // 2) from SettingInfo
1555   auto &rec = SettingInfo[index];
1556 
1557   switch (rec.type) {
1558     case cSetting_blank:
1559       break;
1560     case cSetting_boolean:
1561     case cSetting_int:
1562       I->info[index].set_i(rec.value.i[0]);
1563       break;
1564     case cSetting_float:
1565       I->info[index].set_f(rec.value.f[0]);
1566       break;
1567     case cSetting_float3:
1568       I->info[index].set_3f(rec.value.f);
1569       break;
1570     case cSetting_string:
1571       I->info[index].delete_s();
1572       break;
1573     case cSetting_color:
1574       SettingSet_color(I, index, rec.value.s);
1575       break;
1576     default:
1577       // coding error
1578       printf(" ERROR: unkown type\n");
1579   };
1580 
1581   I->info[index].defined = false;
1582 }
1583 
1584 
1585 /*========================================================================*/
SettingUnset(CSetting * I,int index)1586 int SettingUnset(CSetting * I, int index)
1587 {
1588   if(I) {
1589     SettingRec *sr = I->info + index;
1590     if (!sr->defined) {
1591       return false;
1592     }
1593     sr->defined = false;
1594     sr->changed = true;
1595   }
1596   return true;
1597 }
1598 
1599 
1600 /*========================================================================*/
SettingGetType(int index)1601 int SettingGetType(int index)
1602 {
1603   return (SettingInfo[index].type);
1604 }
1605 
1606 
1607 /*========================================================================*/
1608 template <>
SettingGet(int index,const CSetting * I)1609 int SettingGet<int>(int index, const CSetting * I)
1610 {
1611   PyMOLGlobals *G = I->G;
1612   int result;
1613   switch (SettingInfo[index].type) {
1614   case cSetting_boolean:
1615   case cSetting_int:
1616   case cSetting_color:
1617     result = I->info[index].int_;
1618     break;
1619   case cSetting_float:
1620     result = (int) I->info[index].float_;
1621     break;
1622   default:
1623     PRINTFB(G, FB_Setting, FB_Errors)
1624       "Setting-Error: type read mismatch (int) %d\n", index ENDFB(G);
1625     result = 0;
1626     break;
1627   }
1628   return (result);
1629 }
1630 
1631 
1632 /*========================================================================*/
1633 template <>
SettingGet(int index,const CSetting * I)1634 bool SettingGet<bool>(int index, const CSetting * I)
1635 {
1636   PyMOLGlobals *G = I->G;
1637   switch (SettingInfo[index].type) {
1638   case cSetting_boolean:
1639   case cSetting_int:
1640   case cSetting_float:
1641     return I->info[index].int_ != 0;
1642   default:
1643     PRINTFB(G, FB_Setting, FB_Errors)
1644       "Setting-Error: type read mismatch (boolean) %d\n", index ENDFB(G);
1645     return false;
1646   }
1647 }
1648 
1649 
1650 /*========================================================================*/
1651 template <>
SettingGet(int index,const CSetting * I)1652 float SettingGet<float>(int index, const CSetting * I)
1653 {
1654   float result;
1655   PyMOLGlobals *G = I->G;
1656   switch (SettingInfo[index].type) {
1657   case cSetting_color:
1658     PRINTFB(G, FB_Setting, FB_Warnings)
1659       " Setting-Warning: type read mismatch (float/color) %d\n", index ENDFB(G);
1660   case cSetting_boolean:
1661   case cSetting_int:
1662     result = (float) I->info[index].int_;
1663     break;
1664   case cSetting_float:
1665     result = I->info[index].float_;
1666     break;
1667   default:
1668     PRINTFB(G, FB_Setting, FB_Errors)
1669       "Setting-Error: type read mismatch (float) %d\n", index ENDFB(G);
1670     result = 0.0F;
1671   }
1672   return (result);
1673 }
1674 
1675 
1676 /*========================================================================*/
1677 template <>
SettingGet(int index,const CSetting * I)1678 const char * SettingGet<const char *>(int index, const CSetting * I)
1679 {
1680   const char *result;
1681   PyMOLGlobals *G = I->G;
1682   switch (SettingInfo[index].type) {
1683   case cSetting_string:
1684     if(I->info[index].str_) {
1685       result = I->info[index].str_->c_str();
1686     } else {
1687       result = SettingInfo[index].value.s;
1688     }
1689     break;
1690   default:
1691     PRINTFB(G, FB_Setting, FB_Errors)
1692       "Setting-Error: type read mismatch (string) %d\n", index ENDFB(G);
1693     result = NULL;
1694   }
1695   return (char*) result;
1696 }
1697 
1698 
1699 /*========================================================================*/
1700 template <>
SettingGet(int index,const CSetting * I)1701 const float * SettingGet<const float *>(int index, const CSetting * I)
1702 {
1703   if (SettingInfo[index].type != cSetting_float3) {
1704     PyMOLGlobals *G = I->G;
1705     PRINTFB(G, FB_Setting, FB_Errors)
1706       " Setting-Error: type read mismatch (float3) %d\n", index ENDFB(G);
1707     return NULL;
1708   }
1709   return I->info[index].float3_;
1710 }
1711 
1712 
1713 /*========================================================================*/
SettingSet_i(CSetting * I,int index,int value)1714 int SettingSet_i(CSetting * I, int index, int value)
1715 {
1716   int ok = true;
1717   if(I) {
1718     PyMOLGlobals *G = I->G;
1719     {
1720       int setting_type = SettingInfo[index].type;
1721       switch (setting_type) {
1722       case cSetting_boolean:
1723       case cSetting_int:
1724       case cSetting_color:
1725         I->info[index].set_i(value);
1726 	break;
1727       case cSetting_float:
1728         I->info[index].set_f((float) value);
1729 	break;
1730       default:
1731 	PRINTFB(G, FB_Setting, FB_Errors)
1732 	  "Setting-Error: type set mismatch (integer) %d\n", index ENDFB(G);
1733 	ok = false;
1734       }
1735     }
1736   } else {
1737     ok = false;
1738   }
1739   return (ok);
1740 }
1741 
1742 
1743 /*========================================================================*/
SettingSet_color_from_3f(CSetting * I,int index,const float * vector)1744 static int SettingSet_color_from_3f(CSetting * I, int index, const float * vector)
1745 {
1746   int color_index;
1747   float vals[3];
1748   copy3f(vector, vals);
1749   clamp3f(vals);
1750   color_index = Color3fToInt(I->G, vals);
1751   return SettingSet_i(I, index, color_index);
1752 }
1753 
SettingSet_color(CSetting * I,int index,const char * value)1754 int SettingSet_color(CSetting * I, int index, const char *value)
1755 {
1756   int ok = true;
1757   int color_index;
1758   if(I) {
1759     PyMOLGlobals *G = I->G;
1760     color_index = ColorGetIndex(G, value);
1761     if((color_index == -1) && (strcmp(value, "-1") &&
1762                                strcmp(value, "-2") &&
1763                                strcmp(value, "-3") &&
1764                                strcmp(value, "-4") &&
1765                                strcmp(value, "-5") && strcmp(value, "default"))) {
1766       float vals[3];
1767       ok = ParseFloat3List(value, vals);
1768       if (ok){
1769 	clamp3f(vals);
1770 	color_index = cColor_TRGB_Bits |
1771 	  ((int) (255 * vals[0] + 0.49999F)) << 16 |
1772 	  ((int) (255 * vals[1] + 0.49999F)) << 8 |
1773 	  ((int) (255 * vals[2] + 0.49999F));
1774       } else {
1775 	PRINTFB(G, FB_Setting, FB_Errors)
1776 	  "Setting-Error: unknown color '%s'\n", value ENDFB(G);
1777       }
1778     }
1779     if (ok){
1780       SettingSet_i(I, index, color_index);
1781     }
1782   }
1783   return (ok);
1784 }
1785 
1786 
1787 /*========================================================================*/
SettingSet_f(CSetting * I,int index,float value)1788 int SettingSet_f(CSetting * I, int index, float value)
1789 {
1790   int ok = true;
1791   if(I) {
1792     PyMOLGlobals *G = I->G;
1793     {
1794       int setting_type = SettingInfo[index].type;
1795       switch (setting_type) {
1796       case cSetting_boolean:
1797       case cSetting_int:
1798       case cSetting_color:
1799         I->info[index].set_i((int) value);
1800 	break;
1801       case cSetting_float:
1802         I->info[index].set_f(value);
1803 	break;
1804       default:
1805 	PRINTFB(G, FB_Setting, FB_Errors)
1806 	  "Setting-Error: type set mismatch (float) %d\n", index ENDFB(G);
1807 	ok = false;
1808       }
1809     }
1810   } else {
1811     ok = false;
1812   }
1813   return (ok);
1814 }
1815 
1816 
1817 /*========================================================================*/
SettingSet_s(CSetting * I,int index,const char * value)1818 int SettingSet_s(CSetting * I, int index, const char *value)
1819 {
1820   int ok = true;
1821   if(I) {
1822     PyMOLGlobals *G = I->G;
1823     {
1824       int setting_type = SettingInfo[index].type;
1825       switch (setting_type) {
1826       case cSetting_string:
1827         I->info[index].set_s(value);
1828 	break;
1829       case cSetting_color:
1830         return SettingSet_color(I, index, value);
1831       default:
1832 	PRINTFB(G, FB_Setting, FB_Errors)
1833 	  "Setting-Error: type set mismatch (string) %d\n", index ENDFB(G);
1834 	ok = false;
1835       }
1836     }
1837   } else {
1838     ok = false;
1839   }
1840   return (ok);
1841 }
1842 
1843 
1844 /*========================================================================*/
SettingSet_3fv(CSetting * I,int index,const float * vector)1845 int SettingSet_3fv(CSetting * I, int index, const float *vector)
1846 {
1847   switch (SettingInfo[index].type) {
1848   case cSetting_float3:
1849     I->info[index].set_3f(vector);
1850     return true;
1851   case cSetting_color:
1852     return SettingSet_color_from_3f(I, index, vector);
1853   default:
1854     PyMOLGlobals *G = I->G;
1855     PRINTFB(G, FB_Setting, FB_Errors)
1856       "Setting-Error: type set mismatch (float3) %d\n", index ENDFB(G);
1857     return false;
1858   }
1859 }
1860 
1861 
1862 /*========================================================================*/
SettingGetIndex(PyMOLGlobals * G,const char * name)1863 int SettingGetIndex(PyMOLGlobals * G, const char *name)
1864 {
1865   OVreturn_word result = get_setting_id(G->PyMOL, name);
1866 
1867   if (OVreturn_IS_OK(result))
1868     return result.word;
1869 
1870   return -1;
1871 }
1872 
1873 
1874 /*========================================================================*/
SettingGetName(PyMOLGlobals * G,int index,SettingName name)1875 int SettingGetName(PyMOLGlobals * G, int index, SettingName name)
1876 {
1877   UtilNCopy(name, SettingInfo[index].name, sizeof(SettingName));
1878   return (name[0] != 0);
1879 }
1880 
1881 /*========================================================================*/
SettingGetName(int index)1882 const char * SettingGetName(int index)
1883 {
1884   return SettingInfo[index].name;
1885 }
1886 
1887 /*========================================================================*/
SettingGenerateSideEffects(PyMOLGlobals * G,int index,const char * sele,int state,int quiet)1888 void SettingGenerateSideEffects(PyMOLGlobals * G, int index, const char *sele, int state, int quiet)
1889 {
1890   const char *inv_sele = (sele && sele[0]) ? sele : cKeywordAll;
1891   auto &rec = SettingInfo[index];
1892 
1893   if (rec.level == cSettingLevel_unused) {
1894     const char * name = rec.name;
1895 
1896     if (!quiet && name && name[0]){
1897       PRINTFB(G, FB_Setting, FB_Warnings)
1898         " Setting-Warning: '%s' is no longer used\n", name
1899         ENDFB(G);
1900     }
1901 
1902     return;
1903   }
1904 
1905   // range check for int (global only)
1906   if (rec.type == cSetting_int && rec.hasMinMax() && !(sele && sele[0])) {
1907     int value = SettingGetGlobal_i(G, index);
1908     bool clamped = true;
1909 
1910     if (value < rec.value.i[1]) {
1911       value = rec.value.i[1];
1912     } else if (value > rec.value.i[2]) {
1913       value = rec.value.i[2];
1914     } else {
1915       clamped = false;
1916     }
1917 
1918     if (clamped) {
1919       PRINTFB(G, FB_Setting, FB_Warnings)
1920         " Setting-Warning: %s range = [%d,%d]; setting to %d.\n",
1921         rec.name, rec.value.i[1], rec.value.i[2], value ENDFB(G);
1922       SettingSetGlobal_i(G, index, value);
1923     }
1924   }
1925 
1926   switch (index) {
1927   case cSetting_stereo:
1928     SceneUpdateStereo(G);
1929     G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
1930     break;
1931   case cSetting_pick_surface:
1932     if (SettingGetGlobal_b(G, cSetting_use_shaders)){
1933       SceneInvalidatePicking(G); // right now, when pick_surface is off, wipes each CGO's pickColor array
1934     }
1935     ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvColor);
1936     break;
1937   case cSetting_pickable:
1938     ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvAll);
1939     SceneChanged(G);
1940     break;
1941   case cSetting_grid_mode:
1942     if (!SettingGetGlobal_i(G, cSetting_grid_mode))
1943       G->ShaderMgr->ResetUniformSet();
1944   case cSetting_grid_slot:
1945     ExecutiveInvalidateGroups(G, false);
1946     SceneChanged(G);
1947     break;
1948   case cSetting_grid_max:
1949     SceneChanged(G);
1950     break;
1951   case cSetting_defer_builds_mode:
1952     ExecutiveRebuildAll(G);
1953     break;
1954   case cSetting_seq_view:
1955   case cSetting_seq_view_label_spacing:
1956   case cSetting_seq_view_label_mode:
1957   case cSetting_seq_view_label_start:
1958   case cSetting_seq_view_format:
1959   case cSetting_seq_view_color:
1960   case cSetting_seq_view_unaligned_mode:
1961   case cSetting_seq_view_gap_mode:
1962     SeqChanged(G);
1963     break;
1964   case cSetting_seq_view_fill_color:
1965   case cSetting_seq_view_fill_char:
1966   case cSetting_seq_view_label_color:
1967     OrthoDirty(G);
1968     break;
1969   case cSetting_show_frame_rate:
1970     OrthoDirty(G);
1971     break;
1972   case cSetting_group_full_member_names:
1973   case cSetting_group_arrow_prefix:
1974     OrthoDirty(G);
1975     break;
1976   case cSetting_static_singletons:
1977     SeqChanged(G);
1978     break;
1979   case cSetting_seq_view_location:
1980     PParse(G, "cmd.viewport(-1,-1)");
1981     SeqChanged(G);
1982     break;
1983   case cSetting_seq_view_overlay:
1984     PParse(G, "cmd.viewport(-1,-1)");
1985     break;
1986   case cSetting_stereo_mode:
1987   case cSetting_anaglyph_mode:
1988     G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
1989     SceneUpdateStereoMode(G);
1990     OrthoInvalidateDoDraw(G);
1991     OrthoDirty(G);
1992     PyMOL_NeedRedisplay(G->PyMOL);
1993     break;
1994   case cSetting_precomputed_lighting:
1995     G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
1996   case cSetting_light_count:
1997   case cSetting_spec_count:
1998     G->ShaderMgr->Set_Reload_Bits(RELOAD_CALLCOMPUTELIGHTING);
1999   case cSetting_dot_lighting:
2000   case cSetting_mesh_lighting:
2001   case cSetting_cgo_lighting:
2002   case cSetting_field_of_view:
2003   case cSetting_fog_start:
2004   case cSetting_two_sided_lighting:
2005   case cSetting_transparency_global_sort:
2006   case cSetting_dot_normals:
2007   case cSetting_mesh_normals:
2008     SceneInvalidate(G);
2009     break;
2010   case cSetting_spec_power:
2011     if (!quiet){
2012       PRINTFB(G, FB_Setting, FB_Debugging)
2013 	"Setting-Details: spec_power is depreciated in PyMOL 1.5.  This option will not work in future versions. Please set shininess to set the specular exponent for movable light sources.\n"
2014 	ENDFB(G);
2015     }
2016     SceneInvalidate(G);
2017     break;
2018   case cSetting_light:
2019   case cSetting_light2:
2020   case cSetting_light3:
2021   case cSetting_light4:
2022   case cSetting_light5:
2023   case cSetting_light6:
2024   case cSetting_light7:
2025   case cSetting_reflect:
2026   case cSetting_direct:
2027   case cSetting_ambient:
2028   case cSetting_specular:
2029   case cSetting_specular_intensity:
2030   case cSetting_shininess:
2031   case cSetting_spec_reflect:
2032   case cSetting_spec_direct:
2033   case cSetting_spec_direct_power:
2034   case cSetting_power:
2035   case cSetting_reflect_power:
2036     if (SettingGetGlobal_b(G, cSetting_precomputed_lighting))
2037       G->ShaderMgr->Set_Reload_Bits(RELOAD_CALLCOMPUTELIGHTING);
2038       SceneInvalidate(G);
2039     break;
2040   case cSetting_use_display_lists:
2041   case cSetting_simplify_display_lists:
2042   case cSetting_excl_display_lists_shaders:
2043     if (!quiet){
2044       PRINTFB(G, FB_Setting, FB_Debugging)
2045 	"Setting-Details: display lists were depreciated in PyMOL 1.7.x.  The settings use_display_lists, simplify_display_lists, and excl_display_lists_shaders no longer work.\n"
2046 	ENDFB(G);
2047     }
2048   case cSetting_use_geometry_shaders:
2049     if (SettingGetGlobal_i(G, cSetting_use_geometry_shaders) &&
2050         G->ShaderMgr->IsConfigured() && !G->ShaderMgr->GeometryShadersPresent()) {
2051       SettingSet_b(G->Setting, cSetting_use_geometry_shaders, 0);
2052       if (!quiet){
2053         PRINTFB(G, FB_Setting, FB_Warnings)
2054           "Setting-Error: geometry shaders not available\n" ENDFB(G);
2055       }
2056       return;
2057     }
2058 
2059     G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
2060     ExecutiveInvalidateRep(G, inv_sele, cRepLabel, cRepInvRep);
2061     {
2062       // check if lines need to be invalidated
2063       bool line_as_cylinders = SettingGetGlobal_b(G, cSetting_use_shaders) &&
2064                                SettingGetGlobal_b(G, cSetting_render_as_cylinders) &&
2065                                SettingGetGlobal_b(G, cSetting_line_as_cylinders);
2066       if (!line_as_cylinders && !SettingGetGlobal_b(G, cSetting_trilines)){
2067         ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
2068       }
2069     }
2070     break;
2071   case cSetting_shaders_from_disk:
2072     G->ShaderMgr->Set_Reload_Bits(RELOAD_ALL_SHADERS);
2073     SceneInvalidate(G);
2074     break;
2075   case cSetting_use_shaders:
2076     {
2077       short changed = 0;
2078       if (SettingGetGlobal_b(G, cSetting_use_shaders)){
2079 	if (SettingCheckUseShaders(G->Setting, quiet)){
2080 	  return;
2081 	}
2082       }
2083       SceneInvalidate(G);
2084       if (SettingGetGlobal_b(G, cSetting_sphere_use_shader)){
2085 	ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
2086 	changed = 1;
2087       }
2088       if (SettingGetGlobal_b(G, cSetting_ribbon_use_shader)){
2089 	ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
2090 	changed = 1;
2091       }
2092       if (SettingGetGlobal_b(G, cSetting_nonbonded_use_shader)){
2093 	ExecutiveInvalidateRep(G, inv_sele, cRepNonbonded, cRepInvRep);
2094 	changed = 1;
2095       }
2096       if (SettingGetGlobal_i(G, cSetting_nb_spheres_use_shader)){
2097 	changed = 1;
2098       }
2099       if (SettingGetGlobal_b(G, cSetting_dash_use_shader)){
2100 	ExecutiveInvalidateRep(G, inv_sele, cRepAngle, cRepInvRep);
2101 	ExecutiveInvalidateRep(G, inv_sele, cRepDihedral, cRepInvRep);
2102 	ExecutiveInvalidateRep(G, inv_sele, cRepDash, cRepInvRep);
2103 	changed = 1;
2104       }
2105       if (SettingGetGlobal_b(G, cSetting_line_use_shader)){
2106 	ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
2107 	changed = 1;
2108       }
2109       if (SettingGetGlobal_b(G, cSetting_cartoon_use_shader)){
2110 	ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
2111 	changed = 1;
2112       }
2113       if (SettingGetGlobal_b(G, cSetting_cgo_use_shader) ||
2114           SettingGetGlobal_b(G, cSetting_stick_as_cylinders)){
2115 	ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
2116 	changed = 1;
2117       }
2118       if (SettingGetGlobal_b(G, cSetting_stick_use_shader) ||
2119           SettingGetGlobal_b(G, cSetting_stick_as_cylinders) ||
2120 	  (SettingGetGlobal_b(G, cSetting_stick_ball) &&
2121 	   SettingGetGlobal_b(G, cSetting_valence))){
2122 	ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2123 	changed = 1;
2124       }
2125       if (SettingGetGlobal_b(G, cSetting_surface_use_shader) ||
2126 	  SettingGetGlobal_b(G, cSetting_dot_use_shader) ||
2127 	  SettingGetGlobal_b(G, cSetting_mesh_use_shader)){
2128 	changed = 1;
2129       }
2130       if (changed){
2131 	SceneChanged(G);
2132       }
2133     }
2134     break;
2135   case cSetting_stereo_shift:
2136   case cSetting_stereo_angle:
2137   case cSetting_stereo_dynamic_strength:
2138     SceneInvalidate(G);
2139     break;
2140   case cSetting_scene_buttons:
2141   case cSetting_scene_buttons_mode:
2142     SceneInvalidate(G);
2143     OrthoInvalidateDoDraw(G);
2144     break;
2145   case cSetting_dash_round_ends:
2146   case cSetting_dash_color:
2147     if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_dash_use_shader)){
2148       ExecutiveInvalidateRep(G, "all", cRepDash, cRepInvRep);
2149     }
2150     SceneInvalidate(G);
2151     break;
2152   case cSetting_angle_color:
2153     if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_dash_use_shader)){
2154       ExecutiveInvalidateRep(G, "all", cRepAngle, cRepInvRep);
2155     }
2156     SceneInvalidate(G);
2157     break;
2158   case cSetting_dihedral_color:
2159     if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_dash_use_shader)){
2160       ExecutiveInvalidateRep(G, "all", cRepDihedral, cRepInvRep);
2161     }
2162     SceneInvalidate(G);
2163     break;
2164   case cSetting_mouse_selection_mode:
2165     OrthoDirty(G);
2166     break;
2167   case cSetting_internal_gui_control_size:
2168     WizardRefresh(G);
2169     OrthoDirty(G);
2170     break;
2171   case cSetting_hide_underscore_names:
2172     ExecutiveInvalidateGroups(G, false);
2173     OrthoDirty(G);
2174     break;
2175   case cSetting_gradient_spacing:
2176   case cSetting_gradient_max_length:
2177   case cSetting_gradient_min_length:
2178   case cSetting_gradient_normal_min_dot:
2179   case cSetting_gradient_step_size:
2180   case cSetting_gradient_min_slope:
2181   case cSetting_gradient_symmetry:
2182     ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvRep);
2183     SceneChanged(G);
2184     break;
2185   case cSetting_min_mesh_spacing:
2186   case cSetting_mesh_grid_max:
2187   case cSetting_mesh_cutoff:
2188   case cSetting_mesh_carve_state:
2189   case cSetting_mesh_carve_cutoff:
2190   case cSetting_mesh_carve_selection:
2191   case cSetting_mesh_clear_state:
2192   case cSetting_mesh_clear_cutoff:
2193   case cSetting_mesh_clear_selection:
2194   case cSetting_mesh_mode:
2195   case cSetting_mesh_type:
2196   case cSetting_mesh_solvent:
2197   case cSetting_mesh_quality:
2198   case cSetting_mesh_skip:
2199     ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvRep);
2200     SceneChanged(G);
2201     break;
2202   case cSetting_valence:
2203   case cSetting_valence_mode:
2204   case cSetting_valence_size:
2205   case cSetting_valence_zero_mode:
2206   case cSetting_valence_zero_scale:
2207   case cSetting_half_bonds:
2208   case cSetting_line_stick_helper:
2209   case cSetting_hide_long_bonds:
2210     ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
2211     ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2212     SceneChanged(G);
2213     break;
2214   case cSetting_stick_transparency:
2215   case cSetting_stick_debug:
2216   case cSetting_stick_round_nub:
2217   case cSetting_stick_as_cylinders:
2218   case cSetting_stick_good_geometry:
2219     ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2220     SceneChanged(G);
2221     break;
2222   case cSetting_line_use_shader:
2223     if (SettingGetGlobal_b(G, cSetting_use_shaders)){
2224       ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
2225       SceneChanged(G);
2226     }
2227     break;
2228   case cSetting_ribbon_use_shader:
2229     if (SettingGetGlobal_b(G, cSetting_use_shaders)){
2230       ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
2231       SceneChanged(G);
2232     }
2233     break;
2234   case cSetting_dot_as_spheres:
2235     SceneInvalidate(G);
2236     SceneChanged(G);
2237     break;
2238   case cSetting_dot_use_shader:
2239     if (SettingGetGlobal_b(G, cSetting_use_shaders)){
2240       ExecutiveInvalidateRep(G, inv_sele, cRepDot, cRepInvRep);
2241       SceneChanged(G);
2242     }
2243     break;
2244   case cSetting_nonbonded_use_shader:
2245     if (SettingGetGlobal_b(G, cSetting_use_shaders)){
2246       ExecutiveInvalidateRep(G, inv_sele, cRepNonbonded, cRepInvRep);
2247       SceneChanged(G);
2248     }
2249     break;
2250   case cSetting_nb_spheres_size:
2251     ExecutiveInvalidateRep(G, inv_sele, cRepNonbondedSphere, cRepInvRep);
2252     SceneChanged(G);
2253     break;
2254   case cSetting_nb_spheres_use_shader:
2255     if (SettingGetGlobal_b(G, cSetting_use_shaders)){
2256       SceneChanged(G);
2257     }
2258     break;
2259   case cSetting_render_as_cylinders:
2260     ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2261   case cSetting_mesh_as_cylinders:
2262   case cSetting_line_as_cylinders:
2263   case cSetting_ribbon_as_cylinders:
2264   case cSetting_dash_as_cylinders:
2265     if (index == cSetting_dash_as_cylinders) {
2266       ExecutiveInvalidateRep(G, inv_sele, cRepAngle, cRepInvRep);
2267       ExecutiveInvalidateRep(G, inv_sele, cRepDihedral, cRepInvRep);
2268       ExecutiveInvalidateRep(G, inv_sele, cRepDash, cRepInvRep);
2269     }
2270   case cSetting_nonbonded_as_cylinders:
2271   case cSetting_alignment_as_cylinders:
2272   case cSetting_cartoon_nucleic_acid_as_cylinders:
2273     if (SettingGetGlobal_b(G, cSetting_render_as_cylinders)){
2274       if (G->ShaderMgr->shaders_present && !G->ShaderMgr->ShaderPrgExists("cylinder")){
2275 	SettingSet_b(G->Setting, cSetting_render_as_cylinders, 0);
2276 	if (!quiet){
2277 	  PRINTFB(G, FB_Setting, FB_Warnings)
2278 	    "Setting-Error: render_as_cylinders cannot be set when the Cylinder Shader is not available, setting render_as_cylinder back to false\n"
2279 	    ENDFB(G);
2280 	}
2281 	return;
2282       }
2283       switch (index){
2284       case cSetting_render_as_cylinders:
2285       case cSetting_cartoon_nucleic_acid_as_cylinders:
2286       case cSetting_use_shaders:
2287 	if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_render_as_cylinders)){
2288 	  ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
2289 	}
2290       }
2291       SceneChanged(G);
2292     }
2293     break;
2294   case cSetting_mesh_use_shader:
2295     if (SettingGetGlobal_b(G, cSetting_use_shaders)){
2296       SceneChanged(G);
2297     }
2298     break;
2299   case cSetting_slice_height_scale:
2300   case cSetting_slice_height_map:
2301   case cSetting_slice_grid:
2302   case cSetting_slice_dynamic_grid:
2303   case cSetting_slice_dynamic_grid_resolution:
2304     ExecutiveInvalidateRep(G, inv_sele, cRepSlice, cRepInvRep);
2305     SceneChanged(G);
2306     break;
2307   case cSetting_label_font_id:
2308   case cSetting_label_size:
2309     ExecutiveInvalidateRep(G, inv_sele, cRepLabel, cRepInvRep);
2310     SceneChanged(G);
2311     break;
2312   case cSetting_retain_order:
2313   case cSetting_pdb_hetatm_sort:
2314   case cSetting_pdb_insertions_go_first:
2315     ExecutiveSort(G, inv_sele);
2316     break;
2317   case cSetting_roving_lines:
2318   case cSetting_roving_sticks:
2319   case cSetting_roving_spheres:
2320   case cSetting_roving_labels:
2321   case cSetting_roving_selection:
2322   case cSetting_roving_ribbon:
2323   case cSetting_roving_cartoon:
2324   case cSetting_roving_polar_contacts:
2325   case cSetting_roving_polar_cutoff:
2326   case cSetting_roving_nonbonded:
2327   case cSetting_roving_nb_spheres:
2328   case cSetting_roving_map1_level:
2329   case cSetting_roving_map2_level:
2330   case cSetting_roving_map3_level:
2331   case cSetting_roving_map1_name:
2332   case cSetting_roving_map2_name:
2333   case cSetting_roving_map3_name:
2334   case cSetting_roving_isosurface:
2335   case cSetting_roving_isomesh:
2336     SceneRovingChanged(G);
2337     break;
2338   case cSetting_roving_byres:
2339   case cSetting_roving_detail:
2340     SceneRovingDirty(G);
2341     break;
2342   case cSetting_dash_transparency:
2343   case cSetting_dash_length:
2344   case cSetting_dash_gap:
2345   case cSetting_dash_radius:
2346   case cSetting_dash_width:
2347   case cSetting_angle_size:
2348   case cSetting_label_digits:
2349   case cSetting_label_distance_digits:
2350   case cSetting_label_angle_digits:
2351   case cSetting_label_dihedral_digits:
2352   case cSetting_angle_label_position:
2353   case cSetting_dihedral_size:
2354   case cSetting_dihedral_label_position:
2355     ExecutiveRebuildAllObjectDist(G);
2356     SceneChanged(G);
2357     break;
2358   case cSetting_button_mode:
2359     EditorMouseInvalid(G);
2360     OrthoDirty(G);
2361     break;
2362   case cSetting_stick_radius:
2363   case cSetting_stick_h_scale:
2364     ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2365     ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);       /* base width */
2366     SceneChanged(G);
2367     break;
2368   case cSetting_nb_spheres_quality:
2369     {
2370       ExecutiveInvalidateRep(G, inv_sele, cRepNonbondedSphere, cRepInvRep);
2371       SceneChanged(G);
2372     }
2373   case cSetting_cgo_sphere_quality:
2374   case cSetting_cgo_debug:
2375     {
2376       ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
2377       SceneChanged(G);
2378       break;
2379     }
2380   case cSetting_stick_quality:
2381   case cSetting_stick_ball:
2382   case cSetting_stick_nub:
2383   case cSetting_stick_ball_ratio:
2384   case cSetting_stick_ball_color:
2385   case cSetting_stick_fixed_radius:
2386   case cSetting_stick_valence_scale:
2387   case cSetting_stick_overlap:
2388   case cSetting_stick_color:
2389   case cSetting_stick_use_shader:
2390     ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2391     SceneChanged(G);
2392     break;
2393   case cSetting_clamp_colors:
2394   case cSetting_ramp_blend_nearby_colors:
2395     ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvColor);
2396     SceneChanged(G);
2397     break;
2398   case cSetting_label_color:
2399   case cSetting_label_outline_color:
2400   case cSetting_label_position:
2401     ExecutiveRebuildAllObjectDist(G);
2402     ExecutiveInvalidateRep(G, inv_sele, cRepLabel, cRepInvRep);
2403     SceneChanged(G);
2404     break;
2405   case cSetting_cartoon_color:
2406     ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
2407     SceneChanged(G);
2408     break;
2409   case cSetting_ribbon_color:
2410     ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
2411     SceneChanged(G);
2412     break;
2413   case cSetting_cgo_line_width:
2414   case cSetting_line_width:
2415     {
2416       GLfloat *range = G->ShaderMgr->GetLineWidthRange();
2417       float line_width = SettingGetGlobal_f(G, index);
2418       {
2419 	if (line_width <= 0.f){
2420 	  PRINTFB(G, FB_Setting, FB_Warnings)
2421 	    " Setting-Warning: %s is set incorrectly (%f), setting to 1\n",
2422             rec.name, line_width ENDFB(G);
2423 	  SettingSetGlobal_f(G, index, 1.f);
2424 	} else if (G->HaveGUI && range[1] > 0.f && line_width > range[1]) {
2425 	  PRINTFB(G, FB_Setting, FB_Warnings)
2426             " Setting-Warning: %s is out of range of the graphics card's "
2427             "capability (range: %f-%f), lines might not be rendered correctly\n",
2428             rec.name, range[0], range[1] ENDFB(G);
2429 	}
2430       }
2431     }
2432   case cSetting_line_color:
2433   case cSetting_line_radius:
2434     ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
2435     ExecutiveInvalidateRep(G, inv_sele, cRepNonbonded, cRepInvRep);
2436     SceneChanged(G);
2437     break;
2438   case cSetting_scenes_changed:
2439     {
2440       int scene_buttons = SettingGetGlobal_i(G, cSetting_scene_buttons);
2441       if (scene_buttons)
2442 	OrthoInvalidateDoDraw(G);
2443     }
2444     break;
2445   case cSetting_button_mode_name:
2446     {
2447       int internal_gui_mode = SettingGetGlobal_i(G, cSetting_internal_gui_mode);
2448       if (internal_gui_mode){
2449 	OrthoInvalidateDoDraw(G);
2450       }
2451     }
2452       break;
2453   case cSetting_scene_current_name:
2454     SceneRestartFrameTimer(G);
2455     break;
2456   case cSetting_mesh_width:
2457     ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvColor);
2458     SceneChanged(G);
2459     break;
2460   case cSetting_ellipsoid_probability:
2461   case cSetting_ellipsoid_scale:
2462   case cSetting_ellipsoid_color:
2463   case cSetting_ellipsoid_transparency:
2464     ExecutiveInvalidateRep(G, inv_sele, cRepEllipsoid, cRepInvRep);
2465     SceneChanged(G);
2466     break;
2467   case cSetting_ellipsoid_quality:
2468   case cSetting_cgo_ellipsoid_quality:
2469     ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
2470     ExecutiveInvalidateRep(G, inv_sele, cRepEllipsoid, cRepInvRep);
2471     SceneChanged(G);
2472     break;
2473   case cSetting_mesh_color:
2474   case cSetting_mesh_negative_color:
2475     ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvColor);
2476     SceneChanged(G);
2477     break;
2478   case cSetting_ray_color_ramps:
2479     ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvColor);
2480     SceneChanged(G);
2481     break;
2482   case cSetting_sphere_mode:
2483     ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
2484     SceneInvalidate(G);
2485     break;
2486   case cSetting_cull_spheres:
2487   case cSetting_sphere_scale:
2488   case cSetting_sphere_transparency:
2489   case cSetting_sphere_solvent:
2490   case cSetting_sphere_point_max_size:
2491   case cSetting_sphere_point_size:
2492   case cSetting_sphere_use_shader:
2493     ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
2494     SceneInvalidate(G);
2495     break;
2496   case cSetting_sphere_quality:
2497     ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2498     ExecutiveInvalidateRep(G, inv_sele, cRepNonbondedSphere, cRepInvRep);
2499     ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
2500     SceneChanged(G);
2501     break;
2502   case cSetting_nonbonded_size:
2503   case cSetting_nonbonded_transparency:
2504     ExecutiveInvalidateRep(G, inv_sele, cRepNonbonded, cRepInvRep);
2505     ExecutiveInvalidateRep(G, inv_sele, cRepNonbondedSphere, cRepInvRep);
2506     SceneChanged(G);
2507     break;
2508   case cSetting_mesh_radius:
2509     ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvColor);
2510     SceneChanged(G);
2511     break;
2512   case cSetting_ambient_occlusion_scale:
2513     SceneChanged(G);
2514     break;
2515   case cSetting_ambient_occlusion_mode:
2516     ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvColor);
2517     switch (SettingGetGlobal_i(G, cSetting_ambient_occlusion_mode) % 4){
2518     case 1:
2519       SettingSetGlobal_i(G, cSetting_ambient_occlusion_smooth, 10);
2520       SettingSetGlobal_f(G, cSetting_ambient_occlusion_scale, 25.f);
2521       break;
2522     case 2:
2523       SettingSetGlobal_i(G, cSetting_ambient_occlusion_smooth, 5);
2524       SettingSetGlobal_f(G, cSetting_ambient_occlusion_scale, .9f);
2525       break;
2526     case 3:
2527       SettingSetGlobal_i(G, cSetting_ambient_occlusion_smooth, 5);
2528       SettingSetGlobal_f(G, cSetting_ambient_occlusion_scale, 1.1f);
2529       break;
2530     }
2531     SceneChanged(G);
2532     break;
2533   case cSetting_ambient_occlusion_smooth:
2534   case cSetting_surface_negative_color:
2535   case cSetting_surface_color:
2536   case cSetting_surface_ramp_above_mode:
2537   case cSetting_transparency:
2538     ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvColor);
2539     SceneChanged(G);
2540     break;
2541   case cSetting_dot_color:
2542     ExecutiveInvalidateRep(G, inv_sele, cRepDot, cRepInvColor);
2543     SceneChanged(G);
2544     break;
2545   case cSetting_sphere_color:
2546     ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvColor);
2547     SceneChanged(G);
2548     break;
2549 
2550   case cSetting_surface_quality:
2551   case cSetting_surface_mode:
2552   case cSetting_surface_normal:
2553   case cSetting_surface_type:
2554   case cSetting_surface_carve_state:
2555   case cSetting_surface_carve_cutoff:
2556   case cSetting_surface_carve_selection:
2557   case cSetting_surface_carve_normal_cutoff:
2558   case cSetting_surface_clear_state:
2559   case cSetting_surface_clear_cutoff:
2560   case cSetting_surface_clear_selection:
2561   case cSetting_surface_trim_cutoff:
2562   case cSetting_surface_trim_factor:
2563   case cSetting_surface_circumscribe:
2564   case cSetting_surface_solvent:
2565   case cSetting_surface_proximity:
2566   case cSetting_surface_cavity_mode:
2567   case cSetting_surface_cavity_radius:
2568   case cSetting_surface_cavity_cutoff:
2569   case cSetting_cavity_cull:
2570   case cSetting_surface_smooth_edges:
2571     ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvRep);
2572     SceneChanged(G);
2573     break;
2574   case cSetting_surface_use_shader:
2575     SceneChanged(G);
2576     break;
2577   case cSetting_surface_negative_visible:
2578     ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvRep);
2579     SceneChanged(G);
2580     break;
2581   case cSetting_mesh_negative_visible:
2582     ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvAll);
2583     SceneChanged(G);
2584     break;
2585   case cSetting_solvent_radius:
2586     ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvRep);
2587     ExecutiveInvalidateRep(G, inv_sele, cRepMesh, cRepInvRep);
2588     ExecutiveInvalidateRep(G, inv_sele, cRepDot, cRepInvRep);
2589     SceneChanged(G);
2590     break;
2591   case cSetting_trace_atoms_mode:
2592     ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
2593     ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
2594     SceneChanged(G);
2595     break;
2596   case cSetting_ribbon_smooth:
2597   case cSetting_ribbon_power:
2598   case cSetting_ribbon_power_b:
2599   case cSetting_ribbon_sampling:
2600   case cSetting_ribbon_radius:
2601   case cSetting_ribbon_width:
2602   case cSetting_ribbon_throw:
2603   case cSetting_ribbon_trace_atoms:
2604   case cSetting_ribbon_transparency:
2605     ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
2606     SceneChanged(G);
2607     break;
2608   case cSetting_draw_mode:
2609     ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2610     ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
2611     break;
2612   case cSetting_cartoon_side_chain_helper:
2613   case cSetting_cartoon_nucleic_acid_mode:
2614     ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
2615     ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
2616     ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2617     ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
2618     ExecutiveInvalidateRep(G, inv_sele, cRepEllipsoid, cRepInvRep);
2619     SceneChanged(G);
2620     break;
2621   case cSetting_ribbon_side_chain_helper:
2622   case cSetting_ribbon_nucleic_acid_mode:
2623     ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
2624     ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
2625     ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2626     ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
2627     ExecutiveInvalidateRep(G, inv_sele, cRepEllipsoid, cRepInvRep);
2628     SceneChanged(G);
2629     break;
2630   case cSetting_ray_trace_mode:        /* affects loop quality */
2631     G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
2632   case cSetting_cartoon_transparency:
2633   case cSetting_cartoon_ring_transparency:
2634   case cSetting_cartoon_trace_atoms:
2635   case cSetting_cartoon_refine:
2636   case cSetting_cartoon_nucleic_acid_color:
2637   case cSetting_cartoon_ring_mode:
2638   case cSetting_cartoon_ring_finder:
2639   case cSetting_cartoon_ring_width:
2640   case cSetting_cartoon_ring_color:
2641   case cSetting_cartoon_ladder_mode:
2642   case cSetting_cartoon_ladder_radius:
2643   case cSetting_cartoon_ladder_color:
2644   case cSetting_cartoon_sampling:
2645   case cSetting_cartoon_loop_quality:
2646   case cSetting_cartoon_loop_radius:
2647   case cSetting_cartoon_loop_cap:
2648   case cSetting_cartoon_tube_quality:
2649   case cSetting_cartoon_tube_radius:
2650   case cSetting_cartoon_tube_cap:
2651   case cSetting_cartoon_putty_quality:
2652   case cSetting_cartoon_putty_radius:
2653   case cSetting_cartoon_putty_range:
2654   case cSetting_cartoon_putty_scale_min:
2655   case cSetting_cartoon_putty_scale_max:
2656   case cSetting_cartoon_putty_scale_power:
2657   case cSetting_cartoon_putty_transform:
2658   case cSetting_cartoon_power:
2659   case cSetting_cartoon_power_b:
2660   case cSetting_cartoon_ring_radius:
2661   case cSetting_cartoon_rect_length:
2662   case cSetting_cartoon_rect_width:
2663   case cSetting_cartoon_oval_length:
2664   case cSetting_cartoon_oval_width:
2665   case cSetting_cartoon_oval_quality:
2666   case cSetting_cartoon_round_helices:
2667   case cSetting_cartoon_flat_sheets:
2668   case cSetting_cartoon_refine_normals:
2669   case cSetting_cartoon_smooth_loops:
2670   case cSetting_cartoon_dumbbell_width:
2671   case cSetting_cartoon_dumbbell_length:
2672   case cSetting_cartoon_dumbbell_radius:
2673   case cSetting_cartoon_fancy_helices:
2674   case cSetting_cartoon_fancy_sheets:
2675   case cSetting_cartoon_cylindrical_helices:
2676   case cSetting_cartoon_refine_tips:
2677   case cSetting_cartoon_helix_radius:
2678   case cSetting_cartoon_throw:
2679   case cSetting_cartoon_debug:
2680   case cSetting_cartoon_highlight_color:
2681   case cSetting_cartoon_discrete_colors:
2682   case cSetting_cartoon_smooth_first:
2683   case cSetting_cartoon_smooth_last:
2684   case cSetting_cartoon_smooth_cycles:
2685   case cSetting_cartoon_flat_cycles:
2686   case cSetting_cartoon_gap_cutoff:
2687   case cSetting_cartoon_all_alt:
2688     ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
2689     SceneChanged(G);
2690     break;
2691   case cSetting_cartoon_use_shader:
2692     if (SettingGetGlobal_b(G, cSetting_use_shaders)){
2693       ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
2694       SceneChanged(G);
2695     }
2696     break;
2697   case cSetting_cgo_use_shader:
2698     if (SettingGetGlobal_b(G, cSetting_use_shaders)){
2699       ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
2700       SceneChanged(G);
2701     }
2702     break;
2703   case cSetting_cgo_shader_ub_flags:
2704     if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_cgo_use_shader)){
2705       ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
2706       SceneChanged(G);
2707     }
2708     break;
2709   case cSetting_cgo_shader_ub_color:
2710     if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_cgo_use_shader)){
2711       ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
2712       ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
2713       ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
2714       SceneChanged(G);
2715     }
2716     break;
2717   case cSetting_cgo_shader_ub_normal:
2718     if (SettingGetGlobal_b(G, cSetting_use_shaders) && SettingGetGlobal_b(G, cSetting_cgo_use_shader)){
2719       ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvRep);
2720       ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
2721       // if spheres rendered with geometry, then normals are used
2722       // this should really only invalidate spheres that use normals (sphere_mode=0, not sure about other modes)
2723       // but invalidating all spheres for now
2724       ExecutiveInvalidateRep(G, inv_sele, cRepSphere, cRepInvRep);
2725       SceneChanged(G);
2726     }
2727     break;
2728   case cSetting_trilines:
2729      ExecutiveInvalidateRep(G, inv_sele, cRepLine, cRepInvRep);
2730      ExecutiveInvalidateRep(G, inv_sele, cRepCyl, cRepInvRep);
2731      ExecutiveInvalidateRep(G, inv_sele, cRepRibbon, cRepInvRep);
2732      ExecutiveInvalidateRep(G, inv_sele, cRepCartoon, cRepInvRep);
2733      ExecutiveInvalidateRep(G, inv_sele, cRepDash, cRepInvRep);
2734      ExecutiveInvalidateRep(G, inv_sele, cRepNonbonded, cRepInvRep);
2735      SceneChanged(G);
2736      break;
2737   case cSetting_dot_width:
2738   case cSetting_dot_radius:
2739   case cSetting_dot_density:
2740   case cSetting_dot_mode:
2741   case cSetting_dot_solvent:
2742   case cSetting_dot_hydrogens:
2743   case cSetting_trim_dots:
2744     ExecutiveInvalidateRep(G, inv_sele, cRepDot, cRepInvRep);
2745     SceneChanged(G);
2746     break;
2747   case cSetting_bg_gradient:
2748       ColorUpdateFrontFromSettings(G);
2749       ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvColor);
2750     G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
2751     SceneChanged(G);
2752     break;
2753   case cSetting_bg_image_mode:
2754   case cSetting_bg_image_filename:
2755     G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
2756   case cSetting_bg_image_linear:
2757   case cSetting_bg_image_tilesize:
2758     OrthoBackgroundTextureNeedsUpdate(G);
2759     SceneChanged(G);
2760     break;
2761   case cSetting_bg_rgb_top:
2762   case cSetting_bg_rgb_bottom:
2763     {
2764       /* clamp this value */
2765       const char * bg_image_filename = SettingGet_s(G, NULL, NULL, cSetting_bg_image_filename);
2766       if(!(bg_image_filename && bg_image_filename[0]) &&
2767           SettingGetGlobal_b(G, cSetting_bg_gradient) && !OrthoBackgroundDataIsSet(*G->Ortho)) {
2768         ColorUpdateFrontFromSettings(G);
2769 	ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvColor);
2770 	OrthoBackgroundTextureNeedsUpdate(G);
2771       }
2772     }
2773     SceneChanged(G);
2774     break;
2775   case cSetting_bg_rgb:
2776     {
2777       /* clamp this value */
2778       const float *v = ColorGet(G, SettingGet_color(G, NULL, NULL, cSetting_bg_rgb));
2779       {
2780         const char * bg_image_filename = SettingGet_s(G, NULL, NULL, cSetting_bg_image_filename);
2781         if(!(bg_image_filename && bg_image_filename[0]) && !OrthoBackgroundDataIsSet(*G->Ortho)) {
2782 	  ColorUpdateFront(G, v);
2783 	  ExecutiveInvalidateRep(G, inv_sele, cRepAll, cRepInvColor);
2784 	}
2785       }
2786     }
2787     SceneChanged(G);
2788     break;
2789   case cSetting_selection_width:
2790   case cSetting_selection_width_scale:
2791   case cSetting_selection_width_max:
2792   case cSetting_selection_round_points:
2793     ExecutiveInvalidateSelectionIndicatorsCGO(G);
2794   case cSetting_line_smooth:
2795   case cSetting_ortho:
2796   case cSetting_chromadepth:
2797   case cSetting_transparency_mode:
2798   if (index == cSetting_transparency_mode)
2799 #ifdef _WEBGL
2800 #endif
2801     ExecutiveInvalidateRep(G, inv_sele, cRepCGO, cRepInvAll);
2802   case cSetting_depth_cue:
2803   case cSetting_fog:
2804   case cSetting_ray_transparency_oblique:
2805     G->ShaderMgr->Set_Reload_Bits(RELOAD_VARIABLES);
2806   case cSetting_ray_transparency_oblique_power:
2807     SceneInvalidate(G);
2808     break;
2809   case cSetting_sculpting:
2810     OrthoDirty(G);
2811     break;
2812   case cSetting_auto_overlay:
2813     OrthoRemoveAutoOverlay(G); /* always start clean */
2814     break;
2815   case cSetting_overlay:
2816   case cSetting_overlay_lines:
2817   case cSetting_text:
2818     OrthoDirty(G);
2819     break;
2820   case cSetting_internal_gui_mode:
2821   case cSetting_internal_gui_width:
2822   case cSetting_internal_gui:
2823   case cSetting_internal_feedback:
2824   case cSetting_mouse_grid:
2825   case cSetting_movie_panel_row_height:
2826   case cSetting_movie_panel:
2827     if(!SettingGetGlobal_b(G, cSetting_suspend_updates)) {
2828       OrthoCommandIn(G, "viewport");
2829     }
2830     break;
2831   case cSetting_suspend_updates:
2832     if(!SettingGetGlobal_b(G, cSetting_suspend_updates)) {
2833       SceneChanged(G);          /* force big update upon resumption */
2834       OrthoDirty(G);
2835     }
2836     break;
2837   case cSetting_security:
2838     G->Security = SettingGetGlobal_i(G, cSetting_security);
2839     break;
2840   case cSetting_state:
2841     if (SettingGet<int>(G, index) < 0 /* all */) {
2842       PRINTFB(G, FB_Setting, FB_Warnings)
2843         " Setting-Warning: state can't be less than 0.\n" ENDFB(G);
2844     }
2845   case cSetting_all_states:
2846   case cSetting_frame:
2847     ExecutiveInvalidateSelectionIndicatorsCGO(G);
2848     SceneInvalidatePicking(G);
2849     SceneChanged(G);
2850     break;
2851   case cSetting_dynamic_width:
2852   case cSetting_dynamic_width_factor:
2853   case cSetting_dynamic_width_min:
2854   case cSetting_dynamic_width_max:
2855     SceneChanged(G);
2856     break;
2857   case cSetting_rock:
2858   case cSetting_sweep_mode:
2859   case cSetting_sweep_phase:
2860   case cSetting_sweep_angle:
2861   case cSetting_sweep_speed:
2862     SceneRestartSweepTimer(G);
2863     break;
2864   case cSetting_motion_power:
2865   case cSetting_motion_bias:
2866   case cSetting_motion_simple:
2867   case cSetting_motion_linear:
2868   case cSetting_motion_hand:
2869   case cSetting_movie_loop:
2870     if(SettingGetGlobal_b(G, cSetting_movie_auto_interpolate)) {
2871       ExecutiveMotionReinterpolate(G);
2872     }
2873     break;
2874   case cSetting_volume_bit_depth:
2875     ExecutiveInvalidateRep(G, inv_sele, cRepVolume, cRepInvAll);
2876     SceneInvalidate(G);
2877     break;
2878   case cSetting_volume_layers:
2879     ExecutiveInvalidateRep(G, inv_sele, cRepVolume, cRepInvColor);
2880     SceneInvalidate(G);
2881     break;
2882   case cSetting_cgo_transparency:
2883     SceneInvalidate(G);
2884     SceneChanged(G);
2885     break;
2886   case cSetting_label_connector_mode:
2887     {
2888       int lc_mode = SettingGetGlobal_i(G, cSetting_label_connector_mode);
2889       if(lc_mode < 0 || lc_mode > 4){
2890 	if (!quiet){
2891 	  PRINTFB(G, FB_Setting, FB_Warnings)
2892 	    "Setting-Warning: label_connector_mode range = [0,4]"
2893 	    ENDFB(G);
2894 	}
2895       }
2896     }
2897   case cSetting_float_labels:
2898   case cSetting_label_z_target:
2899   case cSetting_label_connector:
2900   case cSetting_label_connector_color:
2901   case cSetting_label_connector_width:
2902   case cSetting_label_connector_ext_length:
2903   case cSetting_label_bg_color:
2904   case cSetting_label_placement_offset:
2905   case cSetting_label_relative_mode:
2906   case cSetting_label_screen_point:
2907   case cSetting_label_multiline_spacing:
2908   case cSetting_label_multiline_justification:
2909   case cSetting_label_padding:
2910   case cSetting_label_bg_transparency:
2911   case cSetting_label_bg_outline:
2912   case cSetting_ray_label_connector_flat:
2913     ExecutiveInvalidateRep(G, inv_sele, cRepLabel, cRepInvAll );
2914     break;
2915   case cSetting_surface_color_smoothing:
2916   case cSetting_surface_color_smoothing_threshold:
2917     ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvColor);
2918     SceneChanged(G);
2919     break;
2920   case cSetting_smooth_half_bonds:
2921     SceneChanged(G);
2922     break;
2923   case cSetting_antialias_shader:
2924   case cSetting_atom_type_format:
2925   case cSetting_colored_feedback:
2926   case cSetting_load_atom_props_default:
2927   case cSetting_load_object_props_default:
2928   case cSetting_suspend_undo:
2929   case cSetting_volume_mode:
2930     PRINTFB(G, FB_Setting, FB_Warnings)
2931       " Setting-Warning: %s is not supported in Open-Source version of PyMOL\n",
2932       SettingInfo[index].name
2933       ENDFB(G);
2934     break;
2935     break;
2936   case cSetting_surface_debug:
2937     if (SettingGetGlobal_b(G, cSetting_use_shaders)){
2938       ExecutiveInvalidateRep(G, inv_sele, cRepSurface, cRepInvColor);
2939     }
2940     break;
2941   case cSetting_pick32bit:
2942     SceneInvalidatePicking(G);
2943     break;
2944   case cSetting_display_scale_factor:
2945   {
2946     int scaleFactor = SettingGetGlobal_i(G, cSetting_display_scale_factor);
2947     if (scaleFactor > 0) {
2948       _gScaleFactor = scaleFactor;
2949       ExecutiveInvalidateRep(G, NULL, cRepLabel, cRepInvRep);
2950       OrthoCommandIn(G, "viewport");
2951     } else {
2952       SettingSetGlobal_i(G, cSetting_display_scale_factor, 1);
2953       PRINTFB(G, FB_Setting, FB_Warnings)
2954         "Setting-Error: Cannot set a display scale factor of 0\n"
2955         ENDFB(G);
2956     }
2957     break;
2958   }
2959 #ifdef _PYMOL_OPENVR
2960   case cSetting_openvr_gui_distance:
2961   case cSetting_openvr_gui_fov:
2962   // case cSetting_openvr_gui_alpha:
2963   // case cSetting_openvr_gui_use_alpha:
2964   case cSetting_openvr_gui_scene_color:
2965   case cSetting_openvr_gui_scene_alpha:
2966   case cSetting_openvr_gui_back_color:
2967   case cSetting_openvr_gui_back_alpha:
2968   // case cSetting_openvr_gui_use_backdrop:
2969   // case cSetting_openvr_gui_overlay:
2970   // case cSetting_openvr_gui_text:
2971     OpenVRMenuSettingsChanged(G);
2972     break;
2973   case cSetting_openvr_disable_clipping:
2974     OpenVRClippingChanged(G);
2975     break;
2976   case cSetting_openvr_laser_width:
2977     OpenVRLaserWidthChanged(G);
2978     break;
2979 #endif
2980   default:
2981     break;
2982   }
2983 }
2984 
2985 
2986 /*========================================================================*/
SettingFreeGlobal(PyMOLGlobals * G)2987 void SettingFreeGlobal(PyMOLGlobals * G)
2988 {
2989   CSetting *I = G->Setting;
2990   SettingUniqueFree(G);
2991   SettingPurge(I);
2992   if(G->Default) {
2993     SettingPurge(G->Default);
2994     FreeP(G->Default);
2995   }
2996   FreeP(G->Setting);
2997 }
2998 
2999 
3000 /*========================================================================*/
SettingInitGlobal(PyMOLGlobals * G,int alloc,int reset_gui,int use_default)3001 void SettingInitGlobal(PyMOLGlobals * G, int alloc, int reset_gui, int use_default)
3002 {
3003   CSetting *I = G->Setting;
3004 
3005   /* use function pointers to prevent the compiler from inlining every
3006      call in this block (a waste of RAM and time) */
3007 
3008   int (*set_i) (CSetting * I, int index, int value) = SettingSet_i;
3009   int (*set_b) (CSetting * I, int index, int value) = SettingSet_b;
3010 
3011   if(alloc || !I) {
3012     I = (G->Setting = pymol::calloc<CSetting>(1));
3013     SettingUniqueInit(G);
3014     SettingInit(G, I);
3015   }
3016 
3017   if(G->Default && use_default) {
3018 
3019     SettingCopyAll(G, G->Default, G->Setting);
3020 
3021   } else {
3022 
3023     // copy defaults from SettingInfo table
3024     for(int index = 0; index < cSetting_INIT; ++index) {
3025       if (!reset_gui) switch (index) {
3026         case cSetting_internal_gui_width:
3027         case cSetting_internal_gui:
3028           continue;
3029       }
3030 
3031       SettingRestoreDefault(I, index);
3032     }
3033 
3034     // open-source has no volume_mode=1
3035     set_i(I, cSetting_volume_mode, 0);
3036 
3037     // command line arguments overwrites
3038     set_b(I, cSetting_auto_show_lines, G->Option->sphere_mode < 0);
3039     set_i(I, cSetting_auto_zoom, G->Option->zoom_mode);
3040     set_b(I, cSetting_auto_show_nonbonded, G->Option->sphere_mode < 0);
3041     set_b(I, cSetting_presentation, G->Option->presentation);
3042     set_i(I, cSetting_defer_builds_mode, G->Option->defer_builds_mode);
3043     set_b(I, cSetting_presentation_auto_quit, !G->Option->no_quit);
3044     set_b(I, cSetting_auto_show_spheres, G->Option->sphere_mode >= 0);
3045     set_i(I, cSetting_internal_feedback, G->Option->internal_feedback);
3046 
3047     if(G->Option->stereo_mode) {
3048       set_i(I, cSetting_stereo_mode, G->Option->stereo_mode);
3049     } else if(G->StereoCapable || G->Option->blue_line) {
3050       set_i(I, cSetting_stereo_mode, cStereo_quadbuffer);      /* quadbuffer if we can */
3051     }
3052 
3053     /* In order to get electrostatic potentials in kT from the Coulomb equation...
3054 
3055        PyMOL charges: Q, in e
3056        PyMOL distances: r, in Angstrom
3057        Coulomb Constant: K = 8.987552e9 ((J*m)/(C^2))
3058        Angstrom Convertor: 1 A = 1e-10 m
3059        Coulomb Convertor: 1 e = 1.60217733e-19 C
3060        Angstrom Convertor: 1 A = 10e-10 m
3061        Dielectric Constant: D (unitless)
3062 
3063        ePot = (KQ)/(Dr) =
3064 
3065        8.987552e9 J*m     1.6021773e-19 C   1.6021773e-19 C      1 A        Q
3066        ---------------- * --------------- * --------------- * ---------- * --- =
3067        C^2              1 e               1 e            1e-10 m     Dr
3068 
3069        2.3070795237e-18 J*A      Q
3070        = ---------------------- * ---
3071        e^2               Dr
3072 
3073        Boltzmann Constant: k = 1.380658e-23 (J/K)
3074        Temperature: 300 Kelvin
3075 
3076        kT = 1.380658e-23 * 300 = 4.141974e-21 J
3077 
3078        2.3070795237e-18 J*A         1 kT             Q
3079        ePot = --------------------- * ------------------ * ---
3080        e^2              4.141974e-21 J       Dr
3081 
3082        557.00000 kT*A    Q
3083        ePot = -------------- * --- which will give kT/e units when applied
3084        e^2           Dr
3085      */
3086 
3087 #ifdef WIN32
3088     /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
3089     set_b(I, cSetting_cache_display, 0);
3090 
3091     // PYMOL-3143/PYMOL-3181 Intel HD Graphics
3092     // 4.5.0 - Build *.20.100.*
3093     // Driver update breaks lighting
3094     set_b(I, cSetting_precomputed_lighting, 1);
3095 
3096 #ifndef _PYMOL_ACTIVEX
3097     {
3098       SYSTEM_INFO SysInfo;
3099       GetSystemInfo(&SysInfo);
3100       {
3101         DWORD count = SysInfo.dwNumberOfProcessors;
3102         if(count > 1) {
3103           set_i(I, cSetting_max_threads, count);
3104         }
3105       }
3106     }
3107     /* END PROPRIETARY CODE SEGMENT */
3108 #endif
3109 #endif
3110 
3111 #ifndef _PYMOL_FREETYPE
3112     set_i(I, cSetting_label_font_id, 0);
3113 #endif
3114 
3115 #ifdef _PYMOL_IOS
3116 #endif
3117   }
3118   G->ShaderMgr->Set_Reload_Bits(RELOAD_ALL_SHADERS);
3119 }
3120 
SettingCheckFontID(PyMOLGlobals * G,CSetting * set1,CSetting * set2,int font_id)3121 int SettingCheckFontID(PyMOLGlobals * G, CSetting * set1, CSetting * set2, int font_id){
3122   int ret = font_id;
3123   if (font_id < 5){  // we are no longer supporting GLUT labels since they are not resizeable
3124     PRINTFB(G, FB_Setting, FB_Warnings)
3125       "RepLabel-Warning: GLUT labels (label_font_id 0-4) are no longer available for labelling\n    the scene since they are not resizeable label_font_id=%d setting back to 5 (default) \n",
3126       font_id  ENDFB(G);
3127     if (SettingGet_i(G, set1, NULL, cSetting_label_font_id) == font_id && SettingSet_i(set1, cSetting_label_font_id, 5)){
3128     } else if (SettingGet_i(G, set2, NULL, cSetting_label_font_id) == font_id && SettingSet_i(set2, cSetting_label_font_id, 5)){
3129     } else if (SettingGetGlobal_i(G, cSetting_label_font_id) == font_id){
3130       SettingSetGlobal_i(G, cSetting_label_font_id, 5);
3131     };
3132     ret = 5;
3133   }
3134   return ret;
3135 }
3136 
3137 /*
3138  * State index iterator constructor, see Setting.h for documentation.
3139  */
StateIterator(PyMOLGlobals * G,CSetting * set,int state_,int nstate)3140 StateIterator::StateIterator(PyMOLGlobals * G, CSetting * set, int state_, int nstate) {
3141   if(state_ == -2) {
3142     // current state
3143     state_ = SettingGet_i(G, set, NULL, cSetting_state) - 1;
3144   }
3145 
3146   if(state_ == -1) {
3147     // all states
3148     state = 0;
3149     end = nstate;
3150   } else {
3151     // given state or static singleton
3152     state = (state_ > 0 && nstate == 1
3153         && SettingGet_b(G, set, NULL, cSetting_static_singletons)) ? 0 : state_;
3154     end = state + 1;
3155   }
3156 
3157   if (state < 0)
3158     state = 0;
3159 
3160   if (end > nstate)
3161     end = nstate;
3162 
3163   state--;
3164 }
3165 
StateIterator(CObject * obj,int state_)3166 StateIterator::StateIterator(CObject* obj, int state_)
3167     : StateIterator(obj->G, obj->Setting, state_, obj->getNFrame())
3168 {
3169 }
3170 
3171 /*
3172  * Helper function to init CPyMOL.Setting, a (name: index) dictionary.
3173  * Called in PyMOL_InitAPI
3174  */
CPyMOLInitSetting(OVLexicon * Lex,OVOneToOne * Setting)3175 bool CPyMOLInitSetting(OVLexicon * Lex, OVOneToOne * Setting) {
3176   for(int index = 0; index < cSetting_INIT; ++index) {
3177     auto &rec = SettingInfo[index];
3178 
3179     if (rec.level == cSettingLevel_unused)
3180       continue;
3181 
3182     OVreturn_word result = OVLexicon_GetFromCString(Lex, rec.name);
3183 
3184     if( !OVreturn_IS_OK(result) ||
3185         !OVreturn_IS_OK(OVOneToOne_Set(Setting, result.word, index)))
3186       return false;
3187   }
3188 
3189   return true;
3190 }
3191 
3192 #ifndef _PYMOL_NOPY
3193 /*
3194  * Export the settings names to Python a as (name: index) dictionary.
3195  * Replacement for pymol.settings.SettingIndex
3196  */
SettingGetSettingIndices()3197 PyObject * SettingGetSettingIndices() {
3198   PyObject * val;
3199   PyObject * dict = PyDict_New();
3200 
3201   for(int index = 0; index < cSetting_INIT; ++index) {
3202     auto &rec = SettingInfo[index];
3203 
3204     if (rec.level == cSettingLevel_unused)
3205       continue;
3206 
3207     if ((val = PyInt_FromLong(index))) {
3208       PyDict_SetItemString(dict, rec.name, val);
3209       Py_DECREF(val);
3210     }
3211   }
3212 
3213   return dict;
3214 }
3215 
3216 /*
3217  * Return a list of all setting indices for the given unique id
3218  */
SettingUniqueGetIndicesAsPyList(PyMOLGlobals * G,int unique_id)3219 PyObject * SettingUniqueGetIndicesAsPyList(PyMOLGlobals * G, int unique_id)
3220 {
3221   CSettingUnique *I = G->SettingUnique;
3222   PyObject * list = PyList_New(0);
3223   OVreturn_word result;
3224 
3225   if(unique_id && OVreturn_IS_OK(result = OVOneToOne_GetForward(I->id2offset, unique_id))) {
3226     SettingUniqueEntry *entry;
3227     for (int offset = result.word; offset; offset = entry->next) {
3228       entry = I->entry + offset;
3229       PyObject *item = PyInt_FromLong(entry->setting_id);
3230       PyList_Append(list, item);
3231       Py_DECREF(item);
3232     }
3233   }
3234 
3235   return list;
3236 }
3237 #endif
3238 
3239 /*
3240  * Getters for templatted programming
3241  */
3242 
_SettingGetFirstDefined(int index,PyMOLGlobals * G,const CSetting * set1,const CSetting * set2)3243 const CSetting * _SettingGetFirstDefined(int index,
3244     PyMOLGlobals * G,
3245     const CSetting * set1,
3246     const CSetting * set2) {
3247   if (set1 && set1->info[index].defined)
3248     return set1;
3249   if (set2 && set2->info[index].defined)
3250     return set2;
3251   return G->Setting;
3252 }
3253