Project file update for elbeem
[blender-staging.git] / source / blender / python / api2_2x / gen_utils.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * This is a new part of Blender.
27  *
28  * Contributor(s): Michel Selten, Willian P. Germano, Alex Mole, Ken Hughes
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31 */
32
33 #include "gen_utils.h" /*This must come first*/
34
35 #include "DNA_text_types.h"
36 #include "MEM_guardedalloc.h"
37 #include "BLI_blenlib.h"
38 #include "BIF_space.h"
39 #include "BKE_global.h"
40 #include "BKE_main.h"
41
42 #include "constant.h"
43
44 //---------------------- EXPP_GetModuleConstant -------------------------
45 //Helper function for returning a module constant
46 PyObject *EXPP_GetModuleConstant(char *module, char *constant)
47 {
48         PyObject *py_module = NULL, *py_dict = NULL, *py_constant = NULL;
49
50         /*Careful to pass the correct Package.Module string here or
51         * else you add a empty module somewhere*/
52         py_module = PyImport_AddModule(module);
53         if(!py_module){   //null = error returning module
54                 return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
55                         "error encountered with returning module constant..." ) );
56         }
57         py_dict = PyModule_GetDict(py_module); //never fails
58
59         py_constant = PyDict_GetItemString(py_dict, constant);
60         if(!py_constant){   //null = key not found
61                 return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
62                         "error encountered with returning module constant..." ) );
63         }
64
65         return EXPP_incr_ret(py_constant);
66 }
67
68 /*****************************************************************************/
69 /* Description: This function clamps an int to the given interval         */
70 /*                                                      [min, max].        */
71 /*****************************************************************************/
72 int EXPP_ClampInt( int value, int min, int max )
73 {
74         if( value < min )
75                 return min;
76         else if( value > max )
77                 return max;
78         return value;
79 }
80
81 /*****************************************************************************/
82 /* Description: This function clamps a float to the given interval       */
83 /*                                                      [min, max].      */
84 /*****************************************************************************/
85 float EXPP_ClampFloat( float value, float min, float max )
86 {
87         if( value < min )
88                 return min;
89         else if( value > max )
90                 return max;
91         return value;
92 }
93
94 /*****************************************************************************/
95 /* Description: This function returns true if both given strings are equal,  */
96 /*              otherwise it returns false.                             */
97 /*****************************************************************************/
98 int StringEqual( const char *string1, const char *string2 )
99 {
100         return ( strcmp( string1, string2 ) == 0 );
101 }
102
103 /*****************************************************************************/
104 /* Description: This function returns the name of the given ID struct    */
105 /*               without the Object type identifying characters prepended.   */
106 /*****************************************************************************/
107 char *GetIdName( ID * id )
108 {
109         return ( ( id->name ) + 2 );
110 }
111
112 /*****************************************************************************/
113 /* Description: This function returns the ID of the object with given name   */
114 /*              from a given list.                                          */
115 /*****************************************************************************/
116 ID *GetIdFromList( ListBase * list, char *name )
117 {
118         ID *id = list->first;
119
120         while( id ) {
121                 if( strcmp( name, id->name + 2 ) == 0 )
122                         break;
123                 id = id->next;
124         }
125
126         return id;
127 }
128
129 /*****************************************************************************/
130 /* Description: These functions set an internal string with the given type   */
131 /*                and error_msg arguments.                                   */
132 /*****************************************************************************/
133
134 PyObject *EXPP_ReturnPyObjError( PyObject * type, char *error_msg )
135 {                               /* same as above, just to change its name smoothly */
136         PyErr_SetString( type, error_msg );
137         return NULL;
138 }
139
140 int EXPP_ReturnIntError( PyObject * type, char *error_msg )
141 {
142         PyErr_SetString( type, error_msg );
143         return -1;
144 }
145
146
147 int EXPP_intError(PyObject *type, const char *format, ...)
148 {
149         char *error = "";
150         va_list vlist;
151
152         va_start(vlist, format);
153         vsprintf(error, format, vlist);
154         va_end(vlist);
155
156         PyErr_SetString(type, error);
157         return -1;
158 }
159 //Like EXPP_ReturnPyObjError but takes a printf format string and multiple arguments
160 PyObject *EXPP_objError(PyObject *type, const char *format, ...)
161 {
162         char *error = "";
163         va_list vlist;
164
165         va_start(vlist, format);
166         vsprintf(error, format, vlist);
167         va_end(vlist);
168
169         PyErr_SetString(type, error);
170         return NULL;
171 }
172
173 /*****************************************************************************/
174 /* Description: This function increments the reference count of the given   */
175 /*                       Python object (usually Py_None) and returns it.    */
176 /*****************************************************************************/
177
178 PyObject *EXPP_incr_ret( PyObject * object )
179 {
180         Py_INCREF( object );
181         return ( object );
182 }
183
184 /* return Py_False - to avoid warnings, we use the fact that
185  * 0 == False in Python: */
186 PyObject *EXPP_incr_ret_False()
187 {
188         return Py_BuildValue("i", 0);
189 }
190
191 /* return Py_True - to avoid warnings, we use the fact that
192  * 1 == True in Python: */
193 PyObject *EXPP_incr_ret_True()
194 {
195         return Py_BuildValue("i", 1);
196 }
197
198 void EXPP_incr2( PyObject * ob1, PyObject * ob2 )
199 {
200             Py_INCREF( ob1 );
201             Py_INCREF( ob2 );
202 }
203
204 void EXPP_incr3( PyObject * ob1, PyObject * ob2, PyObject * ob3 )
205 {
206             Py_INCREF( ob1 );
207             Py_INCREF( ob2 );
208             Py_INCREF( ob3 );
209 }
210
211 void EXPP_decr2( PyObject * ob1, PyObject * ob2 )
212 {
213             Py_DECREF( ob1 );
214             Py_DECREF( ob2 );
215 }
216
217 void EXPP_decr3( PyObject * ob1, PyObject * ob2, PyObject * ob3 )
218 {
219             Py_DECREF( ob1 );
220             Py_DECREF( ob2 );
221             Py_DECREF( ob3 );
222 }
223 /*****************************************************************************/
224 /* Description: This function maps the event identifier to a string.      */
225 /*****************************************************************************/
226 char *event_to_name( short event )
227 {
228         switch ( event ) {
229         case SCRIPT_FRAMECHANGED:
230                 return "FrameChanged";
231         case SCRIPT_ONLOAD:
232                 return "OnLoad";
233         case SCRIPT_ONSAVE:
234                 return "OnSave";
235         case SCRIPT_REDRAW:
236                 return "Redraw";
237         case SCRIPT_RENDER:
238                 return "Render";
239         case SCRIPT_POSTRENDER:
240                 return "PostRender";
241         default:
242                 return "Unknown";
243         }
244 }
245
246 /*****************************************************************************/
247 /* Description: Checks whether all objects in a PySequence are of a same  */
248 /*              given type.  Returns 0 if not, 1 on success.             */
249 /*****************************************************************************/
250 int EXPP_check_sequence_consistency( PyObject * seq, PyTypeObject * against )
251 {
252         PyObject *ob;
253         int len = PySequence_Length( seq );
254         int i, result = 1;
255
256         for( i = 0; i < len; i++ ) {
257                 ob = PySequence_GetItem( seq, i );
258                 if( ob == Py_None )
259                         result = 2;
260                 else if( ob->ob_type != against ) {
261                         Py_DECREF( ob );
262                         return 0;
263                 }
264                 Py_DECREF( ob );
265         }
266         return result;          /* 1 if all of 'against' type, 2 if there are (also) Nones */
267 }
268
269 PyObject *EXPP_tuple_repr( PyObject * self, int size )
270 {
271         PyObject *repr, *item;
272         int i;
273
274 /*@     note: a value must be built because the list is decrefed!
275  * otherwise we have nirvana pointers inside python.. */
276
277         repr = PyString_FromString( "" );
278         if( !repr )
279                 return 0;
280
281         item = PySequence_GetItem( self, 0 );
282         PyString_ConcatAndDel( &repr, PyObject_Repr( item ) );
283         Py_DECREF( item );
284
285         for( i = 1; i < size; i++ ) {
286                 item = PySequence_GetItem( self, i );
287                 PyString_ConcatAndDel( &repr, PyObject_Repr( item ) );
288                 Py_DECREF( item );
289         }
290
291         return repr;
292 }
293
294 /****************************************************************************/
295 /* Description: searches through a map for a pair with a given name. If the */
296 /*               pair is present, its ival is stored in *ival and nonzero is */
297 /*               returned. If the pair is absent, zero is returned.     */
298 /****************************************************************************/
299 int EXPP_map_getIntVal( const EXPP_map_pair * map, const char *sval,
300                         int *ival )
301 {
302         while( map->sval ) {
303                 if( StringEqual( sval, map->sval ) ) {
304                         *ival = map->ival;
305                         return 1;
306                 }
307                 ++map;
308         }
309         return 0;
310 }
311
312 /* same as above, but string case is ignored */
313 int EXPP_map_case_getIntVal( const EXPP_map_pair * map, const char *sval,
314                              int *ival )
315 {
316         while( map->sval ) {
317                 if( !BLI_strcasecmp( sval, map->sval ) ) {
318                         *ival = map->ival;
319                         return 1;
320                 }
321                 ++map;
322         }
323         return 0;
324 }
325
326 /****************************************************************************/
327 /* Description: searches through a map for a pair with a given name. If the */
328 /*               pair is present, its ival is stored in *ival and nonzero is */
329 /*              returned. If the pair is absent, zero is returned.           */
330 /* note: this function is identical to EXPP_map_getIntVal except that the  */
331 /*              output is stored in a short value.                         */
332 /****************************************************************************/
333 int EXPP_map_getShortVal( const EXPP_map_pair * map,
334                           const char *sval, short *ival )
335 {
336         while( map->sval ) {
337                 if( StringEqual( sval, map->sval ) ) {
338                         *ival = (short)map->ival;
339                         return 1;
340                 }
341                 ++map;
342         }
343         return 0;
344 }
345
346 /****************************************************************************/
347 /* Description: searches through a map for a pair with a given ival. If the */
348 /*              pair is present, a pointer to its name is stored in *sval */
349 /*              and nonzero is returned. If the pair is absent, zero is */
350 /*              returned.                                               */
351 /****************************************************************************/
352 int EXPP_map_getStrVal( const EXPP_map_pair * map, int ival,
353                         const char **sval )
354 {
355         while( map->sval ) {
356                 if( ival == map->ival ) {
357                         *sval = map->sval;
358                         return 1;
359                 }
360                 ++map;
361         }
362         return 0;
363 }
364
365 /* Redraw wrappers */
366
367 /* this queues redraws if we're not in background mode: */
368 void EXPP_allqueue(unsigned short event, short val)
369 {
370         if (!G.background) allqueue(event, val);
371 }
372
373 /************************************************************************/
374 /* Scriptlink-related functions, used by scene, object, etc. bpyobjects */
375 /************************************************************************/
376 PyObject *EXPP_getScriptLinks( ScriptLink * slink, PyObject * args,
377                                int is_scene )
378 {
379         PyObject *list = NULL;
380         char *eventname = NULL;
381         int i, event = 0;
382
383         /* actually !scriptlink shouldn't happen ... */
384         if( !slink || !slink->totscript )
385                 return EXPP_incr_ret( Py_None );
386
387         if( !PyArg_ParseTuple( args, "s", &eventname ) )
388                 return EXPP_ReturnPyObjError( PyExc_TypeError,
389                                               "expected event name (string) as argument" );
390
391         list = PyList_New( 0 );
392         if( !list )
393                 return EXPP_ReturnPyObjError( PyExc_MemoryError,
394                                               "couldn't create PyList!" );
395
396         if( !strcmp( eventname, "FrameChanged" ) )
397                 event = SCRIPT_FRAMECHANGED;
398         else if( !strcmp( eventname, "Redraw" ) )
399                 event = SCRIPT_REDRAW;
400         else if( !strcmp( eventname, "Render" ) )
401                 event = SCRIPT_RENDER;
402         else if( is_scene && !strcmp( eventname, "OnLoad" ) )
403                 event = SCRIPT_ONLOAD;
404         else if( is_scene && !strcmp( eventname, "OnSave" ) )
405                 event = SCRIPT_ONSAVE;
406         else
407                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
408                                               "invalid event name" );
409
410         for( i = 0; i < slink->totscript; i++ ) {
411                 if( ( slink->flag[i] == event ) && slink->scripts[i] )
412                         PyList_Append( list,
413                                        PyString_FromString( slink->scripts[i]->
414                                                             name + 2 ) );
415         }
416
417         return list;
418 }
419
420 PyObject *EXPP_clearScriptLinks( ScriptLink * slink, PyObject * args )
421 {
422         int i, j, totLinks, deleted = 0;
423         PyObject *seq = NULL;
424         ID **stmp = NULL;
425         short *ftmp = NULL;
426
427         /* check for an optional list of strings */
428         if( !PyArg_ParseTuple( args, "|O", &seq ) )
429                 return ( EXPP_ReturnPyObjError
430                          ( PyExc_TypeError,
431                            "expected no arguments or a list of strings" ) );
432
433
434         /* if there was a parameter, handle it */
435         if ( seq != NULL ) {
436                 /* check that parameter IS list of strings */
437                 if ( !PyList_Check ( seq ) )
438                         return ( EXPP_ReturnPyObjError
439                                  ( PyExc_TypeError,
440                                    "expected a list of strings" ) );
441
442                 totLinks = PyList_Size ( seq );
443                 for ( i = 0 ; i < totLinks ; ++i ) {
444                         if ( !PyString_Check ( PySequence_GetItem( seq, i ) ) )
445                                 return ( EXPP_ReturnPyObjError
446                                          ( PyExc_TypeError,
447                                            "expected list to contain strings" ) );
448                 }
449
450                 /*
451                   parameters OK: now look for each script, and delete
452                   its link as we find it (this handles multiple links)
453                 */
454                 for ( i = 0 ; i < totLinks ; ++i )
455                 {
456                         char *str;
457                         str = PyString_AsString ( PySequence_GetItem( seq, i ) );
458                         for ( j = 0 ; j < slink->totscript ; ++j ) {
459                                 if ( slink->scripts[j] && !strcmp ( slink->scripts[j]->name+2, str ) ) {
460                                         slink->scripts[j] = NULL;
461                                         ++deleted; 
462                                 }
463                         }
464                 }
465         }
466         /* if no parameter, then delete all scripts */
467         else {
468                 deleted = slink->totscript;
469         }
470
471         /*
472            if not all scripts deleted, create new lists and copy remaining
473            links to them
474         */
475
476         if ( slink->totscript > deleted ) {
477                 slink->totscript = slink->totscript - (short)deleted;
478
479                 stmp = slink->scripts;
480                 slink->scripts =
481                         MEM_mallocN( sizeof( ID * ) * ( slink->totscript ),
482                                      "bpySlinkL" );
483
484                 ftmp = slink->flag;
485                 slink->flag =
486                         MEM_mallocN( sizeof( short * ) * ( slink->totscript ),
487                                      "bpySlinkF" );
488
489                 for ( i = 0, j = 0 ; i < slink->totscript ; ++j ) {
490                         if ( stmp[j] != NULL ) {
491                                 memcpy( slink->scripts+i, stmp+j, sizeof( ID * ) );
492                                 memcpy( slink->flag+i, ftmp+j, sizeof( short ) );
493                                 ++i;
494                         }
495                 }
496                 MEM_freeN( stmp );
497                 MEM_freeN( ftmp );
498
499                 /*EXPP_allqueue (REDRAWBUTSSCRIPT, 0 );*/
500                 slink->actscript = 1;
501         } else {
502
503         /* all scripts deleted, so delete entire list and free memory */
504
505                 if( slink->scripts )
506                         MEM_freeN( slink->scripts );
507                 if( slink->flag )
508                         MEM_freeN( slink->flag );
509
510                 slink->scripts = NULL;
511                 slink->flag = NULL;
512                 slink->totscript = slink->actscript = 0;
513         }
514
515         return EXPP_incr_ret( Py_None );
516 }
517
518
519 PyObject *EXPP_addScriptLink(ScriptLink *slink, PyObject *args, int is_scene)
520 {
521         int event = 0, found_txt = 0;
522         void *stmp = NULL, *ftmp = NULL;
523         Text *bltxt = G.main->text.first;
524         char *textname = NULL;
525         char *eventname = NULL;
526
527         /* !scriptlink shouldn't happen ... */
528         if( !slink ) {
529                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
530                         "internal error: no scriptlink!" );
531         }
532
533         if( !PyArg_ParseTuple( args, "ss", &textname, &eventname ) )
534                 return EXPP_ReturnPyObjError( PyExc_TypeError,
535             "expected two strings as arguments" );
536
537         while( bltxt ) {
538                 if( !strcmp( bltxt->id.name + 2, textname ) ) {
539                         found_txt = 1;
540                         break;
541                 }
542                 bltxt = bltxt->id.next;
543         }
544
545         if( !found_txt )
546                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
547             "no such Blender Text" );
548
549         if( !strcmp( eventname, "FrameChanged" ) )
550                 event = SCRIPT_FRAMECHANGED;
551         else if( !strcmp( eventname, "Redraw" ) )
552                 event = SCRIPT_REDRAW;
553         else if( !strcmp( eventname, "Render" ) )
554                 event = SCRIPT_RENDER;
555         else if( is_scene && !strcmp( eventname, "OnLoad" ) )
556                 event = SCRIPT_ONLOAD;
557         else if( is_scene && !strcmp( eventname, "OnSave" ) )
558                 event = SCRIPT_ONSAVE;
559         else
560                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
561                         "invalid event name" );
562
563         stmp = slink->scripts;
564         slink->scripts =
565                 MEM_mallocN( sizeof( ID * ) * ( slink->totscript + 1 ),
566                              "bpySlinkL" );
567
568         ftmp = slink->flag;
569         slink->flag =
570                 MEM_mallocN( sizeof( short * ) * ( slink->totscript + 1 ),
571                              "bpySlinkF" );
572
573         if( slink->totscript ) {
574                 memcpy( slink->scripts, stmp,
575                         sizeof( ID * ) * ( slink->totscript ) );
576                 MEM_freeN( stmp );
577
578                 memcpy( slink->flag, ftmp,
579                         sizeof( short ) * ( slink->totscript ) );
580                 MEM_freeN( ftmp );
581         }
582
583         slink->scripts[slink->totscript] = ( ID * ) bltxt;
584         slink->flag[slink->totscript] = (short)event;
585
586         slink->totscript++;
587
588         if( slink->actscript < 1 )
589                 slink->actscript = 1;
590
591         return EXPP_incr_ret (Py_None);         /* normal exit */
592 }
593
594 /*
595  * Utility routines to clamp and store various datatypes.  The object type 
596  * is checked and a exception is raised if it's not the correct type.  
597  *
598  * Inputs:
599  *    value: PyObject containing the new value
600  *    param: pointer to destination variable
601  *    max, min: range of values for clamping
602  *    type: kind of pointer and data (uses the same characters as
603  *       PyArgs_ParseTuple() and Py_BuildValue()
604  *
605  * Return 0 on success, -1 on error.
606  */
607
608 int EXPP_setFloatClamped( PyObject *value, float *param,
609                                                                 float min, float max )
610 {
611         if( !PyNumber_Check ( value ) ) {
612                 char errstr[128];
613                 sprintf ( errstr, "expected float argument in [%f,%f]", min, max );
614                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
615         }
616
617         *param = EXPP_ClampFloat( (float)PyFloat_AsDouble( value ), min, max );
618
619         return 0;
620 }
621
622 int EXPP_setIValueClamped( PyObject *value, void *param,
623                                                                 int min, int max, char type )
624 {
625         char errstr[128];
626         int number;
627
628         sprintf ( errstr, "expected int argument in [%d,%d]", min, max );
629
630         if( !PyInt_CheckExact ( value ) )
631                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
632
633         number = PyInt_AS_LONG( value );
634
635         switch ( type ) {
636         case 'b':
637                 *(char *)param = (char)EXPP_ClampInt( number, min, max );
638                 return 0;
639         case 'h':
640                 *(short *)param = (short)EXPP_ClampInt( number, min, max );
641                 return 0;
642         case 'H':
643                 *(unsigned short *)param = (unsigned short)EXPP_ClampInt( number, min, max );
644                 return 0;
645         case 'i':
646                 *(int *)param = EXPP_ClampInt( number, min, max );
647                 return 0;
648         default:
649                 return EXPP_ReturnIntError( PyExc_RuntimeError,
650                            "EXPP_setIValueClamped(): invalid type code" );
651         }
652 }
653
654
655 /*
656  * Utility routines to range-check and store various datatypes.  The object 
657  * type is checked and a exception is raised if it's not the correct type.  
658  * An exception is also raised if the value lies outside of the specified
659  * range.  
660  *
661  * Inputs:
662  *    value: PyObject containing the new value
663  *    param: pointer to destination variable
664  *    max, min: valid range for value
665  *    type: kind of pointer and data (uses the same characters as
666  *       PyArgs_ParseTuple() and Py_BuildValue()
667  *
668  * Return 0 on success, -1 on error.
669  */
670
671 int EXPP_setFloatRange( PyObject *value, float *param,
672                                                                 float min, float max )
673 {
674         char errstr[128];
675         short number;
676
677         sprintf ( errstr, "expected int argument in [%f,%f]", min, max );
678
679         if( !PyNumber_Check ( value ) )
680                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
681
682         number = (short)PyFloat_AsDouble( value );
683         if ( number < min || number > max )
684                 return EXPP_ReturnIntError( PyExc_ValueError, errstr );
685
686         *param = number;
687         return 0;
688 }
689
690 int EXPP_setIValueRange( PyObject *value, void *param,
691                                                                 int min, int max, char type )
692 {
693         char errstr[128];
694         int number;
695
696         sprintf ( errstr, "expected int argument in [%d,%d]", min, max );
697
698         if( !PyInt_CheckExact ( value ) )
699                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
700
701         number = PyInt_AS_LONG( value );
702         if( number < min || number > max )
703                 return EXPP_ReturnIntError( PyExc_ValueError, errstr );
704
705         switch ( type ) {
706         case 'b':
707                 *(char *)param = (char)number;
708                 return 0;
709         case 'h':
710                 *(short *)param = (short)number;
711                 return 0;
712         case 'H':
713                 *(unsigned short *)param = (unsigned short)number;
714                 return 0;
715         case 'i':
716                 *(int *)param = number;
717                 return 0;
718         default:
719                 return EXPP_ReturnIntError( PyExc_RuntimeError,
720                            "EXPP_setIValueRange(): invalid type code" );
721         }
722 }
723
724 /*
725  * Utility routines to handle all attribute setters which use module
726  * constants.  Generic pointer to destination variable is used, and typecast
727  * to the appropriate type based on the "type" specifier.
728  *
729  * Inputs:
730  *    constant: constant_Type value 
731  *    param: pointer to destination variable
732  *    type: kind of pointer and data
733  *
734  * Return 0 on success, -1 on error.
735  */
736
737 int EXPP_setModuleConstant ( BPy_constant *constant, void *param, char type )
738 {
739         PyObject *item;
740
741         if( constant->ob_type != &constant_Type )
742                 return EXPP_ReturnIntError( PyExc_TypeError,
743                            "expected module constant" );
744
745         item = PyDict_GetItemString( constant->dict, "value" );
746         if( !item )
747                 return EXPP_ReturnIntError( PyExc_RuntimeError,
748                            "module constant has no \"value\" key" );
749
750         switch ( type ) {
751         case 'h':
752                 *(short *)param = (short)PyInt_AS_LONG( item );
753                 return 0;
754         case 'i':
755                 *(int *)param = PyInt_AS_LONG( item );
756                 return 0;
757         case 'f':
758                 *(float *)param = (float)PyFloat_AS_DOUBLE( item );
759                 return 0;
760         default:
761                 return EXPP_ReturnIntError( PyExc_RuntimeError,
762                            "EXPP_setModuleConstant(): invalid type code" );
763         }
764 }
765
766 /*
767  * Utility routines to get/set bits in bitfields.  Adapted from code in 
768  * sceneRender.c (thanks, ascotan!).  
769  *
770  * Inputs:
771  *    param: pointer to source/destination variable
772  *    setting: the bit to get/set
773  *    type: pointer type ('h' == short, 'i' == integer)
774  */
775
776 PyObject *EXPP_getBitfield( void *param, int setting, char type )
777 {
778         switch ( type ) {
779         case 'b':
780                 return (*(char *)param & setting)
781                                 ? EXPP_incr_ret_True() : EXPP_incr_ret_False();
782         case 'h':
783                 return (*(short *)param & setting)
784                                 ? EXPP_incr_ret_True() : EXPP_incr_ret_False();
785         case 'i':
786                 return (*(int *)param & setting)
787                                 ? EXPP_incr_ret_True() : EXPP_incr_ret_False();
788         default:
789                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
790                            "EXPP_getBit(): invalid type code" );
791         }
792 }
793
794 int EXPP_setBitfield( PyObject * value, void *param, int setting, char type )
795 {
796         int flag;
797         char errstr[] = "expected TRUE or FALSE (1 or 0)";
798
799         if( !PyInt_CheckExact ( value ) )
800                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
801
802         flag = PyInt_AS_LONG ( value );
803         if( flag != 0 && flag != 1 )
804                 return EXPP_ReturnIntError( PyExc_ValueError, errstr );
805
806         switch ( type ) {
807         case 'b':
808                 if ( flag )
809                         *(char *)param |= setting;
810                 else
811                         *(char *)param &= ~setting;
812                 return 0;
813         case 'h':
814                 if ( flag )
815                         *(short *)param |= setting;
816                 else
817                         *(short *)param &= ~setting;
818                 return 0;
819         case 'i':
820                 if ( flag )
821                         *(int *)param |= setting;
822                 else
823                         *(int *)param &= ~setting;
824                 return 0;
825         default:
826                 return EXPP_ReturnIntError( PyExc_RuntimeError,
827                            "EXPP_setBit(): invalid type code" );
828         }
829 }
830
831 /*
832  * Procedure to handle older setStuff() methods.  Assumes that argument 
833  * is a tuple with one object, and so grabs the object and passes it to
834  * the specified tp_getset setter for the corresponding attribute.
835  */
836
837 PyObject *EXPP_setterWrapper ( PyObject * self, PyObject * args,
838                                 setter func)
839 {
840         int error;
841
842         if ( !PyTuple_Check( args ) || PyTuple_Size( args ) != 1 )
843                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
844                                               "expected tuple of one item" );
845
846         error = func ( self, PySequence_Fast_GET_ITEM( args, 0 ), NULL );
847         if ( !error ) {
848                 Py_INCREF( Py_None );
849                 return Py_None;
850         } else
851                 return NULL;
852 }
853
854 /*
855  * Procedure to handle older setStuff() methods.  Assumes that argument 
856  * is a tuple, so just passes it to the specified tp_getset setter for 
857  * the corresponding attribute.
858  */
859
860 PyObject *EXPP_setterWrapperTuple ( PyObject * self, PyObject * args,
861                                                                         setter func)
862 {
863         int error;
864
865         if ( !PyTuple_Check( args ) )
866                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
867                                               "expected tuple" );
868
869         error = func ( self, args, NULL );
870         if ( !error ) {
871                 Py_INCREF( Py_None );
872                 return Py_None;
873         } else
874                 return NULL;
875 }
876