* blender doesn't need the -w anymore to start in a window
[blender.git] / source / blender / python / api2_2x / Draw.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * This is a new part of Blender.
24  *
25  * Contributor(s): Willian P. Germano, Campbell Barton, Ken Hughes
26  *
27  * ***** END GPL LICENSE BLOCK *****
28 */
29
30 /* This file is the Blender.Draw part of opy_draw.c, from the old
31  * bpython/intern dir, with minor changes to adapt it to the new Python
32  * implementation.      Non-trivial original comments are marked with an
33  * @ symbol at their beginning. */
34
35 #include "Draw.h" /*This must come first*/
36
37 #include "BLI_blenlib.h"
38 #include "MEM_guardedalloc.h"
39 #include "BMF_Api.h"
40 #include "DNA_screen_types.h"
41 #include "BKE_global.h"
42 #include "BKE_image.h"
43 #include "BKE_object.h"
44 #include "BKE_main.h"
45 #include "BKE_utildefines.h"
46 #include "BIF_gl.h"
47 #include "BIF_mywindow.h"
48 #include "BIF_screen.h"
49 #include "BIF_space.h"
50 #include "BIF_interface.h"
51 #include "BIF_toolbox.h"
52 #include "DNA_space_types.h"            /* script struct */
53 #include "Image.h"              /* for accessing Blender.Image objects */
54 #include "IMB_imbuf_types.h"    /* for the IB_rect define */
55 #include "interface.h"
56 #include "mydevice.h"           /*@ for all the event constants */
57 #include "gen_utils.h"
58 #include "Window.h"
59 #include "../BPY_extern.h"
60
61 /* used so we can get G.scene->r.cfra for getting the
62 current image frame, some images change frame if they are a sequence */
63 #include "DNA_scene_types.h"
64
65 /* these delimit the free range for button events */
66 #define EXPP_BUTTON_EVENTS_OFFSET 1001
67 #define EXPP_BUTTON_EVENTS_MIN 0
68 #define EXPP_BUTTON_EVENTS_MAX 15382 /* 16384 - 1 - OFFSET */
69
70 #define ButtonObject_Check(v) ((v)->ob_type == &Button_Type)
71
72 #define UI_METHOD_ERRORCHECK \
73         if (check_button_event(&event) == -1)\
74                 return EXPP_ReturnPyObjError( PyExc_AttributeError,\
75                         "button event argument must be in the range [0, 16382]");\
76         if (callback && !PyCallable_Check(callback))\
77                 return EXPP_ReturnPyObjError( PyExc_ValueError,\
78                         "callback is not a python function");\
79
80 /* pointer to main dictionary defined in Blender.c */
81 extern PyObject *g_blenderdict;
82
83 /*@ hack to flag that window redraw has happened inside slider callback: */
84 int EXPP_disable_force_draw = 0;
85
86 /* forward declarations for internal functions */
87 static void Button_dealloc( PyObject * self );
88 static PyObject *Button_getattr( PyObject * self, char *name );
89 static PyObject *Button_repr( PyObject * self );
90 static PyObject *Button_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type);
91 static int Button_setattr( PyObject * self, char *name, PyObject * v );
92
93 static Button *newbutton( void );
94
95 /* GUI interface routines */
96
97 static void exit_pydraw( SpaceScript * sc, short error );
98 static void exec_callback( SpaceScript * sc, PyObject * callback,
99                            PyObject * args );
100 static void spacescript_do_pywin_buttons( SpaceScript * sc,
101                                           unsigned short event );
102
103 static PyObject *Method_Exit( PyObject * self );
104 static PyObject *Method_Register( PyObject * self, PyObject * args );
105 static PyObject *Method_Redraw( PyObject * self, PyObject * args );
106 static PyObject *Method_Draw( PyObject * self );
107 static PyObject *Method_Create( PyObject * self, PyObject * args );
108 static PyObject *Method_UIBlock( PyObject * self, PyObject * args );
109
110 static PyObject *Method_Button( PyObject * self, PyObject * args );
111 static PyObject *Method_Menu( PyObject * self, PyObject * args );
112 static PyObject *Method_Toggle( PyObject * self, PyObject * args );
113 static PyObject *Method_Slider( PyObject * self, PyObject * args );
114 static PyObject *Method_Scrollbar( PyObject * self, PyObject * args );
115 static PyObject *Method_ColorPicker( PyObject * self, PyObject * args );
116 static PyObject *Method_Normal( PyObject * self, PyObject * args );
117 static PyObject *Method_Number( PyObject * self, PyObject * args );
118 static PyObject *Method_String( PyObject * self, PyObject * args );
119 static PyObject *Method_GetStringWidth( PyObject * self, PyObject * args );
120 static PyObject *Method_Text( PyObject * self, PyObject * args );
121 static PyObject *Method_Label( PyObject * self, PyObject * args );
122 /* by Campbell: */
123 static PyObject *Method_PupMenu( PyObject * self, PyObject * args );
124 static PyObject *Method_PupTreeMenu( PyObject * self, PyObject * args );
125 static PyObject *Method_PupIntInput( PyObject * self, PyObject * args );
126 static PyObject *Method_PupFloatInput( PyObject * self, PyObject * args );
127 static PyObject *Method_PupStrInput( PyObject * self, PyObject * args );
128 static PyObject *Method_BeginAlign( PyObject * self, PyObject * args  );
129 static PyObject *Method_EndAlign( PyObject * self, PyObject * args  );
130 /* next by Jonathan Merritt (lancelet): */
131 static PyObject *Method_Image( PyObject * self, PyObject * args);
132 /* CLEVER NUMBUT */
133 static PyObject *Method_PupBlock( PyObject * self, PyObject * args );
134
135 static uiBlock *Get_uiBlock( void );
136
137 static void py_slider_update( void *butv, void *data2_unused );
138
139 /* hack to get 1 block for the UIBlock, only ever 1 at a time */
140 static uiBlock *uiblock=NULL;
141
142 static char Draw_doc[] = "The Blender.Draw submodule";
143
144 static char Method_UIBlock_doc[] = "(drawfunc, mouse_exit) - Popup dialog where buttons can be drawn (expemental)";
145
146 static char Method_Register_doc[] =
147         "(draw, event, button) - Register callbacks for windowing\n\n\
148 (draw) A function to draw the screen, taking no arguments\n\
149 (event) A function to handle events, taking 2 arguments (evt, val)\n\
150         (evt) The event number\n\
151         (val) The value modifier (for key and mouse press/release)\n\
152 (button) A function to handle button events, taking 1 argument (evt)\n\
153         (evt) The button number\n\n\
154 A None object can be passed if a callback is unused.";
155
156
157 static char Method_Redraw_doc[] = "([after]) - Queue a redraw event\n\n\
158 [after=0] Determines whether the redraw is processed before\n\
159 or after other input events.\n\n\
160 Redraw events are buffered so that regardless of how many events\n\
161 are queued the window only receives one redraw event.";
162
163 static char Method_Draw_doc[] = "() - Force an immediate redraw\n\n\
164 Forced redraws are not buffered, in other words the window is redrawn\n\
165 exactly once for everytime this function is called.";
166
167
168 static char Method_Create_doc[] =
169         "(value) - Create a default Button object\n\n\
170  (value) - The value to store in the button\n\n\
171  Valid values are ints, floats, and strings";
172
173 static char Method_Button_doc[] =
174         "(name, event, x, y, width, height, [tooltip]) - Create a new Button \
175 (push) button\n\n\
176 (name) A string to display on the button\n\
177 (event) The event number to pass to the button event function when activated\n\
178 (x, y) The lower left coordinate of the button\n\
179 (width, height) The button width and height\n\
180 [tooltip=] The button's tooltip\n\n\
181 This function can be called as Button() or PushButton().";
182
183 static char Method_BeginAlign_doc[] =
184         "Buttons after this function will draw aligned (button layout only)";
185
186 static char Method_EndAlign_doc[] =
187         "Use after BeginAlign() to stop aligning the buttons (button layout only).";
188
189 static char Method_Menu_doc[] =
190         "(name, event, x, y, width, height, default, [tooltip]) - Create a new Menu \
191 button\n\n\
192 (name) A string to display on the button\n\
193 (event) The event number to pass to the button event function when activated\n\
194 (x, y) The lower left coordinate of the button\n\
195 (width, height) The button width and height\n\
196 (default) The number of the option to be selected by default\n\
197 [tooltip=" "] The button's tooltip\n\n\
198 The menu options are specified through the name of the\n\
199 button. Options are followed by a format code and separated\n\
200 by the '|' (pipe) character.\n\
201 Valid format codes are\n\
202         %t - The option should be used as the title\n\
203         %xN - The option should set the integer N in the button value.";
204
205 static char Method_Toggle_doc[] =
206         "(name, event, x, y, width, height, default, [tooltip]) - Create a new Toggle \
207 button\n\n\
208 (name) A string to display on the button\n\
209 (event) The event number to pass to the button event function when activated\n\
210 (x, y) The lower left coordinate of the button\n\
211 (width, height) The button width and height\n\
212 (default) An integer (0 or 1) specifying the default state\n\
213 [tooltip=] The button's tooltip";
214
215
216 static char Method_Slider_doc[] =
217         "(name, event, x, y, width, height, initial, min, max, [update, tooltip]) - \
218 Create a new Slider button\n\n\
219 (name) A string to display on the button\n\
220 (event) The event number to pass to the button event function when activated\n\
221 (x, y) The lower left coordinate of the button\n\
222 (width, height) The button width and height\n\
223 (initial, min, max) Three values (int or float) specifying the initial \
224                                 and limit values.\n\
225 [update=1] A value controlling whether the slider will emit events as it \
226 is edited.\n\
227         A non-zero value (default) enables the events. A zero value supresses them.\n\
228 [tooltip=] The button's tooltip";
229
230
231 static char Method_Scrollbar_doc[] =
232         "(event, x, y, width, height, initial, min, max, [update, tooltip]) - Create a \
233 new Scrollbar\n\n\
234 (event) The event number to pass to the button event function when activated\n\
235 (x, y) The lower left coordinate of the button\n\
236 (width, height) The button width and height\n\
237 (initial, min, max) Three values (int or float) specifying the initial and limit values.\n\
238 [update=1] A value controlling whether the slider will emit events as it is edited.\n\
239         A non-zero value (default) enables the events. A zero value supresses them.\n\
240 [tooltip=] The button's tooltip";
241
242 static char Method_ColorPicker_doc[] = 
243         "(event, x, y, width, height, initial, [tooltip]) - Create a new Button \
244 Color picker button\n\n\
245 (event) The event number to pass to the button event function when the color changes\n\
246 (x, y) The lower left coordinate of the button\n\
247 (width, height) The button width and height\n\
248 (initial) 3-Float tuple of the color (values between 0 and 1)\
249 [tooltip=] The button's tooltip";
250
251 static char Method_Normal_doc[] = 
252         "(event, x, y, width, height, initial, [tooltip]) - Create a new Button \
253 Normal button (a sphere that you can roll to change the normal)\n\n\
254 (event) The event number to pass to the button event function when the color changes\n\
255 (x, y) The lower left coordinate of the button\n\
256 (width, height) The button width and height - non square will gave odd results\n\
257 (initial) 3-Float tuple of the normal vector (values between -1 and 1)\
258 [tooltip=] The button's tooltip";
259
260 static char Method_Number_doc[] =
261         "(name, event, x, y, width, height, initial, min, max, [tooltip], [callback], [clickstep], [precision]) - Create a \
262 new Number button\n\n\
263 (name) A string to display on the button\n\
264 (event) The event number to pass to the button event function when activated\n\
265 (x, y) The lower left coordinate of the button\n\
266 (width, height) The button width and height\n\
267 (initial, min, max) Three values (int or float) specifying the initial and \
268 limit values.\n\
269 [tooltip=] The button's tooltip\n\
270 [callback=] The button's callback\n\
271 [clickstep=] Click step for the button\n\
272 [precision=] How many decimal places to maintain, if not given, it is calculated depending on range, otherwise 1,2,3 or 4. Larger values are clamped to 4";
273
274 static char Method_String_doc[] =
275         "(name, event, x, y, width, height, initial, length, [tooltip]) - Create a \
276 new String button\n\n\
277 (name) A string to display on the button\n\
278 (event) The event number to pass to the button event function when activated\n\
279 (x, y) The lower left coordinate of the button\n\
280 (width, height) The button width and height\n\
281 (initial) The string to display initially\n\
282 (length) The maximum input length\n\
283 [tooltip=] The button's tooltip";
284
285 static char Method_GetStringWidth_doc[] =
286         "(text, font = 'normal') - Return the width in pixels of the given string\n\
287 (font) The font size: 'large','normal' (default), 'normalfix', 'small' or 'tiny'.";
288
289 static char Method_Text_doc[] =
290         "(text, font = 'normal') - Draw text onscreen\n\n\
291 (text) The text to draw\n\
292 (font) The font size: 'large','normal' (default), 'normalfix', 'small' or 'tiny'.\n\n\
293 This function returns the width of the drawn string.";
294
295 static char Method_Label_doc[] =
296         "(text, x, y, w, h, tip, callback) - Draw a text label onscreen\n\n\
297 (text) The text to draw\n\
298 (x, y, w, h) The lower left coordinate of the lable, width and height";
299
300 static char Method_PupMenu_doc[] =
301         "(string, maxrow = None) - Display a pop-up menu at the screen.\n\
302 The contents of the pop-up are specified through the 'string' argument,\n\
303 like with Draw.Menu.\n\
304 'maxrow' is an optional int to control how many rows the pop-up should have.\n\
305 Options are followed by a format code and separated\n\
306 by the '|' (pipe) character.\n\
307 Valid format codes are\n\
308         %t - The option should be used as the title\n\
309         %xN - The option should set the integer N in the button value.\n\n\
310 Ex: Draw.PupMenu('OK?%t|QUIT BLENDER') # should be familiar ...";
311
312 static char Method_PupTreeMenu_doc[] =
313 "each item in the menu list should be - (str, event), separator - None or submenu - (str, [...]).";
314
315 static char Method_PupIntInput_doc[] =
316         "(text, default, min, max) - Display an int pop-up input.\n\
317 (text) - text string to display on the button;\n\
318 (default, min, max) - the default, min and max int values for the button;\n\
319 Return the user input value or None on user exit";
320
321 static char Method_PupFloatInput_doc[] =
322         "(text, default, min, max, clickStep, floatLen) - Display a float pop-up input.\n\
323 (text) - text string to display on the button;\n\
324 (default, min, max) - the default, min and max float values for the button;\n\
325 (clickStep) - float increment/decrement for each click on the button arrows;\n\
326 (floatLen) - an integer defining the precision (number of decimal places) of \n\
327 the float value show.\n\
328 Return the user input value or None on user exit";
329
330 static char Method_Image_doc[] =
331         "(image, x, y, zoomx = 1.0, zoomy = 1.0, [clipx, clipy, clipw, cliph])) \n\
332     - Draw an image.\n\
333 (image) - Blender.Image to draw.\n\
334 (x, y) - floats specifying the location of the image.\n\
335 (zoomx, zoomy) - float zoom factors in horizontal and vertical directions.\n\
336 (clipx, clipy, clipw, cliph) - integers specifying a clipping rectangle within the original image.";
337
338 static char Method_PupStrInput_doc[] =
339         "(text, default, max = 20) - Display a float pop-up input.\n\
340 (text) - text string to display on the button;\n\
341 (default) - the initial string to display (truncated to 'max' chars);\n\
342 (max = 20) - The maximum number of chars the user can input;\n\
343 Return the user input value or None on user exit";
344
345 static char Method_PupBlock_doc[] =
346         "(title, sequence) - Display a pop-up block.\n\
347 (title) - The title of the block.\n\
348 (sequence) - A sequence defining what the block contains. \
349 The order of the list is the order of appearance, from top down.\n\
350 Possible format for sequence items:\n\
351 [value is an object created with Create]\n\
352 \ttext: Defines a label in the block\n\
353 \t(text, value, tooltip = ''): Defines a toggle button \n\
354 \t(text, value, min, max, tooltip = ''): Defines a num or string button \n\
355 \t\t\tdepending on the value.\n\
356 \t\tFor string, max is the maximum length of the text and min is unused.\n\
357 Return 1 if the pop-up is confirmed, 0 otherwise. \n\
358 Warning: On cancel, the value objects are brought back to there previous values, \
359 \texcept for string values which will still contain the modified values.\n";
360
361 static char Method_Exit_doc[] = "() - Exit the windowing interface";
362
363 /*This is needed for button callbacks.  Any button that uses a callback gets added to this list.
364   On the C side of drawing begin, this list should be cleared.
365   Each entry is a tuple of the form (button, callback py object)
366 */
367 PyObject *M_Button_List = NULL;
368
369 static struct PyMethodDef Draw_methods[] = {
370         {"Create", (PyCFunction)Method_Create, METH_VARARGS, Method_Create_doc},
371         {"UIBlock", (PyCFunction)Method_UIBlock, METH_VARARGS, Method_UIBlock_doc},
372         {"Button", (PyCFunction)Method_Button, METH_VARARGS, Method_Button_doc},
373         {"Toggle", (PyCFunction)Method_Toggle, METH_VARARGS, Method_Toggle_doc},
374         {"Menu", (PyCFunction)Method_Menu, METH_VARARGS, Method_Menu_doc},
375         {"Slider", (PyCFunction)Method_Slider, METH_VARARGS, Method_Slider_doc},
376         {"Scrollbar", (PyCFunction)Method_Scrollbar, METH_VARARGS, Method_Scrollbar_doc},
377         {"ColorPicker", (PyCFunction)Method_ColorPicker, METH_VARARGS, Method_ColorPicker_doc},
378         {"Normal", (PyCFunction)Method_Normal, METH_VARARGS, Method_Normal_doc},
379         {"Number", (PyCFunction)Method_Number, METH_VARARGS, Method_Number_doc},
380         {"String", (PyCFunction)Method_String, METH_VARARGS, Method_String_doc},
381         {"GetStringWidth", (PyCFunction)Method_GetStringWidth, METH_VARARGS, Method_GetStringWidth_doc},
382         {"Text", (PyCFunction)Method_Text, METH_VARARGS, Method_Text_doc},
383         {"Label", (PyCFunction)Method_Label, METH_VARARGS, Method_Label_doc},
384         {"PupMenu", (PyCFunction)Method_PupMenu, METH_VARARGS, Method_PupMenu_doc},
385         {"PupTreeMenu", (PyCFunction)Method_PupTreeMenu, METH_VARARGS, Method_PupTreeMenu_doc},
386         {"PupIntInput", (PyCFunction)Method_PupIntInput, METH_VARARGS, Method_PupIntInput_doc},
387         {"PupFloatInput", (PyCFunction)Method_PupFloatInput, METH_VARARGS, Method_PupFloatInput_doc},
388         {"PupStrInput", (PyCFunction)Method_PupStrInput, METH_VARARGS, Method_PupStrInput_doc},
389         {"PupBlock", (PyCFunction)Method_PupBlock, METH_VARARGS, Method_PupBlock_doc},
390         {"Image", (PyCFunction)Method_Image, METH_VARARGS, Method_Image_doc},
391         {"Exit", (PyCFunction)Method_Exit, METH_NOARGS, Method_Exit_doc},
392         {"Redraw", (PyCFunction)Method_Redraw, METH_VARARGS, Method_Redraw_doc},
393         {"Draw", (PyCFunction)Method_Draw, METH_NOARGS, Method_Draw_doc},
394         {"Register", (PyCFunction)Method_Register, METH_VARARGS, Method_Register_doc},
395         {"PushButton", (PyCFunction)Method_Button, METH_VARARGS, Method_Button_doc},
396         {"BeginAlign", (PyCFunction)Method_BeginAlign, METH_VARARGS, Method_BeginAlign_doc},
397         {"EndAlign", (PyCFunction)Method_EndAlign, METH_VARARGS, Method_EndAlign_doc},
398         {NULL, NULL, 0, NULL}
399 };
400
401 PyTypeObject Button_Type = {
402         PyObject_HEAD_INIT( NULL ) 0,   /*ob_size */
403         "Button",               /*tp_name */
404         sizeof( Button ),       /*tp_basicsize */
405         0,                      /*tp_itemsize */
406         ( destructor ) Button_dealloc,  /*tp_dealloc */
407         ( printfunc ) 0,        /*tp_print */
408         ( getattrfunc ) Button_getattr, /*tp_getattr */
409         ( setattrfunc ) Button_setattr, /*tp_setattr */
410         NULL,           /*tp_cmp */
411         ( reprfunc ) Button_repr,       /*tp_repr */
412
413         /* Method suites for standard classes */
414
415         NULL,                       /* PyNumberMethods *tp_as_number; */
416         NULL,                       /* PySequenceMethods *tp_as_sequence; */
417         NULL,                       /* PyMappingMethods *tp_as_mapping; */
418
419         /* More standard operations (here for binary compatibility) */
420
421         NULL,                       /* hashfunc tp_hash; */
422         NULL,                       /* ternaryfunc tp_call; */
423         NULL,                       /* reprfunc tp_str; */
424         NULL,                       /* getattrofunc tp_getattro; */
425         NULL,                       /* setattrofunc tp_setattro; */
426
427         /* Functions to access object as input/output buffer */
428         NULL,                       /* PyBufferProcs *tp_as_buffer; */
429
430   /*** Flags to define presence of optional/expanded features ***/
431         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
432
433         NULL,                       /*  char *tp_doc;  Documentation string */
434   /*** Assigned meaning in release 2.0 ***/
435         /* call function for all accessible objects */
436         NULL,                       /* traverseproc tp_traverse; */
437
438         /* delete references to contained objects */
439         NULL,                       /* inquiry tp_clear; */
440
441   /***  Assigned meaning in release 2.1 ***/
442   /*** rich comparisons ***/
443         (richcmpfunc)Button_richcmpr,                       /* richcmpfunc tp_richcompare; */
444
445   /***  weak reference enabler ***/
446         0,                          /* long tp_weaklistoffset; */
447
448   /*** Added in release 2.2 ***/
449         /*   Iterators */
450         NULL,                       /* getiterfunc tp_iter; */
451         NULL,                       /* iternextfunc tp_iternext; */
452
453   /*** Attribute descriptor and subclassing stuff ***/
454         NULL,           /* struct PyMethodDef *tp_methods; */
455         NULL,                       /* struct PyMemberDef *tp_members; */
456         NULL,         /* struct PyGetSetDef *tp_getset; */
457         NULL,                       /* struct _typeobject *tp_base; */
458         NULL,                       /* PyObject *tp_dict; */
459         NULL,                       /* descrgetfunc tp_descr_get; */
460         NULL,                       /* descrsetfunc tp_descr_set; */
461         0,                          /* long tp_dictoffset; */
462         NULL,                       /* initproc tp_init; */
463         NULL,                       /* allocfunc tp_alloc; */
464         NULL,                       /* newfunc tp_new; */
465         /*  Low-level free-memory routine */
466         NULL,                       /* freefunc tp_free;  */
467         /* For PyObject_IS_GC */
468         NULL,                       /* inquiry tp_is_gc;  */
469         NULL,                       /* PyObject *tp_bases; */
470         /* method resolution order */
471         NULL,                       /* PyObject *tp_mro;  */
472         NULL,                       /* PyObject *tp_cache; */
473         NULL,                       /* PyObject *tp_subclasses; */
474         NULL,                       /* PyObject *tp_weaklist; */
475         NULL
476 };
477
478 static void Button_dealloc( PyObject * self )
479 {
480         Button *but = ( Button * ) self;
481
482         if( but->type == BSTRING_TYPE ) {
483                 if( but->val.asstr )
484                         MEM_freeN( but->val.asstr );
485         }
486
487         PyObject_DEL( self );
488 }
489
490 static PyObject *Button_getattr( PyObject * self, char *name )
491 {
492         Button *but = ( Button * ) self;
493         
494         if( strcmp( name, "val" ) == 0 ) {
495                 if( but->type == BINT_TYPE )
496                         return PyInt_FromLong( but->val.asint );
497                 else if( but->type == BFLOAT_TYPE )
498                         return PyFloat_FromDouble( but->val.asfloat );
499                 else if( but->type == BSTRING_TYPE )
500                         return PyString_FromString( but->val.asstr );
501                 else if( but->type == BVECTOR_TYPE )
502                         return Py_BuildValue( "fff", but->val.asvec[0], but->val.asvec[1], but->val.asvec[2] );
503         }
504
505         PyErr_SetString( PyExc_AttributeError, name );
506         return NULL;
507 }
508
509 static int Button_setattr( PyObject * self, char *name, PyObject * v )
510 {
511         Button *but = ( Button * ) self;
512
513         if( strcmp( name, "val" ) == 0 ) {
514                 if( but->type == BINT_TYPE && PyNumber_Check(v) ) {
515                         PyObject *pyVal = PyNumber_Int( v );
516                         if (pyVal) {
517                                 but->val.asint = (int)PyInt_AS_LONG( pyVal );
518                                 Py_DECREF(pyVal);
519                                 return 0;
520                         }
521                 }
522                 else if( but->type == BFLOAT_TYPE && PyNumber_Check(v) ) {
523                         PyObject *pyVal = PyNumber_Float( v );
524                         if (pyVal) {
525                                 but->val.asfloat = (float)PyFloat_AS_DOUBLE( pyVal );
526                                 Py_DECREF(pyVal);
527                                 return 0;
528                         }
529                 }
530                 else if( but->type == BVECTOR_TYPE ) {
531                         if ( PyArg_ParseTuple( v, "fff", but->val.asvec, but->val.asvec+1, but->val.asvec+2 ) )
532                                 return 0;
533                 }
534                 else if( but->type == BSTRING_TYPE && PyString_Check(v) ) {
535                         char *newstr = PyString_AsString(v);
536                         size_t newlen = strlen(newstr);
537                         
538                         if (newlen+1> UI_MAX_DRAW_STR)
539                                 return EXPP_ReturnIntError( PyExc_ValueError, "Error: button string length exceeded max limit (399 chars).");
540
541                         /* if the length of the new string is the same as */
542                         /* the old one, just copy, else delete and realloc. */
543                         if( but->slen == newlen ) {
544                                 BLI_strncpy( but->val.asstr, newstr,
545                                              but->slen + 1 );
546
547                                 return 0;
548
549                         } else {
550                                 MEM_freeN( but->val.asstr );
551                                 but->slen = newlen;
552                                 but->val.asstr =
553                                         MEM_mallocN( but->slen + 1,
554                                                      "button setattr" );
555                                 BLI_strncpy( but->val.asstr, newstr,
556                                              but->slen + 1 );
557
558                                 return 0;
559                         }
560                 }
561         } else {
562                 /*
563                  * Accessing the wrong attribute.
564                  */
565                 return EXPP_ReturnIntError( PyExc_AttributeError, name );
566         }
567
568         /*
569          * Correct attribute but value is incompatible with current button value.
570          */
571         return EXPP_ReturnIntError( PyExc_ValueError, "value incompatible with current button type" );
572 }
573
574 static PyObject *Button_repr( PyObject * self )
575 {
576         return PyObject_Repr( Button_getattr( self, "val" ) );
577 }
578
579 static PyObject *Button_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
580 {
581         PyObject *ret, *valA=NULL, *valB=NULL;
582         if (ButtonObject_Check(objectA))
583                 objectA = valA = Button_getattr( objectA, "val" );
584         if (ButtonObject_Check(objectB))
585                 objectB = valB = Button_getattr( objectB, "val" );
586         ret = PyObject_RichCompare(objectA, objectB, comparison_type);
587         Py_XDECREF(valA); /* Button_getattr created with 1 ref, we dont care about them now */
588         Py_XDECREF(valB);
589         return ret;
590 }
591
592
593 static Button *newbutton( void )
594 {
595         Button *but = NULL;
596         
597         but = ( Button * ) PyObject_NEW( Button, &Button_Type );
598         but->tooltip[0] = 0; /*NULL-terminate tooltip string*/
599         but->tooltip[255] = 0; /*necassary to insure we always have a NULL-terminated string, as
600                                  according to the docs strncpy doesn't do this for us.*/
601         return but;
602 }
603
604 /* GUI interface routines */
605
606 static void exit_pydraw( SpaceScript * sc, short err )
607 {
608         Script *script = NULL;
609
610         if( !sc || !sc->script )
611                 return;
612
613         script = sc->script;
614
615         if( err ) {
616                 PyErr_Print(  );
617                 script->flags = 0;      /* mark script struct for deletion */
618                 SCRIPT_SET_NULL(script);
619                 script->scriptname[0] = '\0';
620                 script->scriptarg[0] = '\0';
621                 error_pyscript();
622                 scrarea_queue_redraw( sc->area );
623         }
624
625         BPy_Set_DrawButtonsList(sc->but_refs);
626         BPy_Free_DrawButtonsList(); /*clear all temp button references*/
627         sc->but_refs = NULL;
628         
629         Py_XDECREF( ( PyObject * ) script->py_draw );
630         Py_XDECREF( ( PyObject * ) script->py_event );
631         Py_XDECREF( ( PyObject * ) script->py_button );
632
633         script->py_draw = script->py_event = script->py_button = NULL;
634 }
635
636 static void exec_callback( SpaceScript * sc, PyObject * callback,
637                            PyObject * args )
638 {
639         PyObject *result = PyObject_CallObject( callback, args );
640
641         if( result == NULL && sc->script ) {    /* errors in the script */
642
643                 if( sc->script->lastspace == SPACE_TEXT ) {     /*if it can be an ALT+P script */
644                         Text *text = G.main->text.first;
645
646                         while( text ) { /* find it and free its compiled code */
647
648                                 if( !strcmp
649                                     ( text->id.name + 2,
650                                       sc->script->id.name + 2 ) ) {
651                                         BPY_free_compiled_text( text );
652                                         break;
653                                 }
654
655                                 text = text->id.next;
656                         }
657                 }
658                 exit_pydraw( sc, 1 );
659         }
660
661         Py_XDECREF( result );
662         Py_XDECREF( args );
663 }
664
665 /* BPY_spacescript_do_pywin_draw, the static spacescript_do_pywin_buttons and
666  * BPY_spacescript_do_pywin_event are the three functions responsible for
667  * calling the draw, buttons and event callbacks registered with Draw.Register
668  * (see Method_Register below).  They are called (only the two BPY_ ones)
669  * from blender/src/drawscript.c */
670
671 void BPY_spacescript_do_pywin_draw( SpaceScript * sc )
672 {
673         uiBlock *block;
674         char butblock[20];
675         Script *script = sc->script;
676         PyGILState_STATE gilstate = PyGILState_Ensure();
677
678         sprintf( butblock, "win %d", curarea->win );
679         block = uiNewBlock( &curarea->uiblocks, butblock, UI_EMBOSSX,
680                             UI_HELV, curarea->win );
681
682         if( script->py_draw ) {
683                 if (sc->but_refs) {
684                         BPy_Set_DrawButtonsList(sc->but_refs);
685                         BPy_Free_DrawButtonsList(); /*clear all temp button references*/
686                 }
687                 sc->but_refs = PyList_New(0);
688                 BPy_Set_DrawButtonsList(sc->but_refs);
689                 
690                 glPushAttrib( GL_ALL_ATTRIB_BITS );
691                 exec_callback( sc, script->py_draw, NULL );
692                 glPopAttrib(  );
693         } else {
694                 glClearColor( 0.4375, 0.4375, 0.4375, 0.0 );
695                 glClear( GL_COLOR_BUFFER_BIT );
696         }
697
698         uiDrawBlock( block );
699
700         curarea->win_swap = WIN_BACK_OK;
701
702         PyGILState_Release(gilstate);
703 }
704
705 static void spacescript_do_pywin_buttons( SpaceScript * sc,
706                                           unsigned short event )
707 {
708         if( sc->script->py_button )
709                 exec_callback( sc, sc->script->py_button,
710                                Py_BuildValue( "(i)", event ) );
711 }
712
713 void BPY_spacescript_do_pywin_event( SpaceScript * sc, unsigned short event,
714         short val, char ascii )
715 {
716         PyGILState_STATE gilstate = PyGILState_Ensure();
717
718         if( event == QKEY && G.qual & ( LR_ALTKEY | LR_CTRLKEY ) ) {
719                 /* finish script: user pressed ALT+Q or CONTROL+Q */
720                 Script *script = sc->script;
721
722                 exit_pydraw( sc, 0 );
723
724                 script->flags &= ~SCRIPT_GUI;   /* we're done with this script */
725
726                 PyGILState_Release(gilstate);
727
728                 return;
729         }
730
731         if (val) {
732
733                 if (uiDoBlocks( &curarea->uiblocks, event, 1 ) != UI_NOTHING) event = 0;
734
735                 if (event == UI_BUT_EVENT) {
736                         /* check that event is in free range for script button events;
737                          * read the comment before check_button_event() below to understand */
738                         if (val >= EXPP_BUTTON_EVENTS_OFFSET && val < 0x4000)
739                                 spacescript_do_pywin_buttons(sc, val - EXPP_BUTTON_EVENTS_OFFSET);
740
741                         PyGILState_Release(gilstate);
742
743                         return;
744                 }
745         }
746
747         /* We use the "event" main module var, used by scriptlinks, to pass the ascii
748          * value to event callbacks (gui/event/button callbacks are not allowed
749          * inside scriptlinks, so this is ok) */
750         if( sc->script->py_event ) {
751                 int pass_ascii = 0;
752                 if (ascii > 31 && ascii != 127) {
753                         pass_ascii = 1;
754                         EXPP_dict_set_item_str(g_blenderdict, "event",
755                                         PyInt_FromLong((long)ascii));
756                 }
757                 exec_callback( sc, sc->script->py_event,
758                         Py_BuildValue( "(ii)", event, val ) );
759                 if (pass_ascii)
760                         EXPP_dict_set_item_str(g_blenderdict, "event",
761                                         PyString_FromString(""));
762         }
763
764         PyGILState_Release(gilstate);
765 }
766
767 static void exec_but_callback(void *pyobj, void *data)
768 {
769         PyObject *result;
770         PyObject *pyvalue = NULL;
771         uiBut *but = (uiBut *)data;
772         PyObject *arg;
773         PyObject *callback = (PyObject *)pyobj;
774         
775         double value = ui_get_but_val(but);
776         
777         if (callback==NULL || callback == Py_None)
778                 return;
779         
780         /* Button types support
781         case MENU:      
782         case TEX:
783         case TOG:
784         case NUMSLI:
785         case NUM:
786         case COL:
787         case BUT_NORMAL:
788         case BUT */
789         switch (but->type) {
790         case TEX:
791                 /*printf("TEX\n");*/
792                 pyvalue = PyString_FromString( (char *)but->poin );
793                 break;
794         case NUM:
795         case NUMSLI:
796         case TOG:
797         case MENU:
798                 if (but->pointype==FLO) {
799                         /*printf("FLO\n");*/
800                         pyvalue = PyFloat_FromDouble( (float)value );
801                 } else if (but->pointype==INT) {
802                         /*printf("INT\n");*/
803                         pyvalue = PyInt_FromLong( (int)value );
804                 } else if (but->pointype==SHO) {
805                         /*printf("SHO\n");*/
806                         pyvalue = PyInt_FromLong( (short)value );
807                 }       
808                 break;
809         case COL:
810         case BUT_NORMAL:
811         {
812                 float vec[3];
813                 VECCOPY(vec, (float *)but->poin);
814                 pyvalue = Py_BuildValue("(fff)", vec[0], vec[1], vec[2]);
815                 break;
816         }
817         case BUT:
818                 pyvalue = Py_None;
819                 Py_INCREF(pyvalue);
820                 break;
821         default:
822                 pyvalue = Py_None;
823                 Py_INCREF(pyvalue);
824                 printf("Error, no button type matched.");
825         }
826         
827         arg = PyTuple_New( 2 );
828         if (uiblock==NULL)
829                 PyTuple_SetItem( arg, 0, PyInt_FromLong(but->retval - EXPP_BUTTON_EVENTS_OFFSET) );
830         else
831                 PyTuple_SetItem( arg, 0, PyInt_FromLong(but->retval) );
832         
833         PyTuple_SetItem( arg, 1, pyvalue );
834         
835         result = PyObject_CallObject( callback, arg );
836         Py_DECREF(arg);
837         
838         if (!result) {
839                 Py_DECREF(pyvalue);
840                 PyErr_Print(  );
841                 error_pyscript(  );
842         }
843         Py_XDECREF( result );
844 }
845
846 /*note that this function populates the drawbutton ref lists.*/
847 static void set_pycallback(uiBut *ubut, PyObject *callback, Button *but)
848 {
849         PyObject *tuple;
850         if (!callback || !PyCallable_Check(callback)) {
851                 if (M_Button_List && but) {
852                         PyList_Append(M_Button_List, (PyObject*)but);
853                 }
854                 return;
855         }
856         
857         if (M_Button_List) {
858                 if (but) tuple = PyTuple_New(2);
859                 else tuple = PyTuple_New(1);
860                 
861                 /*the tuple API mandates this*/
862                 Py_XINCREF(callback);
863                 Py_XINCREF(but); /*this checks for NULL*/
864                 
865                 PyTuple_SET_ITEM(tuple, 0, callback);
866                 if (but) PyTuple_SET_ITEM(tuple, 1, (PyObject*)but);
867                 
868                 PyList_Append(M_Button_List, tuple);
869                 Py_DECREF(tuple); /*we have to do this to aovid double references.*/
870                 
871                 uiButSetFunc(ubut, exec_but_callback, callback, ubut);
872         }
873 }
874
875 void BPy_Set_DrawButtonsList(void *list)
876 {
877         M_Button_List = list;
878 }
879
880 /*this MUST be called after doing UI stuff.*/
881 void BPy_Free_DrawButtonsList(void)
882 {
883         /*Clear the list.*/
884         if (M_Button_List) {
885                 PyGILState_STATE gilstate = {0};
886                 int py_is_on = Py_IsInitialized();
887
888                 if (py_is_on) gilstate = PyGILState_Ensure();
889
890                 PyList_SetSlice(M_Button_List, 0, PyList_Size(M_Button_List), NULL);
891                 Py_DECREF(M_Button_List);
892                 M_Button_List = NULL;
893
894                 if (py_is_on) PyGILState_Release(gilstate);
895         }
896 }
897
898 static PyObject *Method_Exit( PyObject * self )
899 {
900         SpaceScript *sc;
901         Script *script;
902
903         /* if users call Draw.Exit when we are already out of the SPACE_SCRIPT, we
904          * simply return, for compatibility */
905         if( curarea->spacetype == SPACE_SCRIPT )
906                 sc = curarea->spacedata.first;
907         else
908                 Py_RETURN_NONE;
909
910         exit_pydraw( sc, 0 );
911
912         script = sc->script;
913
914         /* remove our lock to the current namespace */
915         script->flags &= ~SCRIPT_GUI;
916         script->scriptname[0] = '\0';
917         script->scriptarg[0] = '\0';
918
919         Py_RETURN_NONE;
920 }
921
922 /* Method_Register (Draw.Register) registers callbacks for drawing, events
923  * and gui button events, so a script can continue executing after the
924  * interpreter reached its end and returned control to Blender.  Everytime
925  * the SPACE_SCRIPT window with this script is redrawn, the registered
926  * callbacks are executed. */
927 static PyObject *Method_Register( PyObject * self, PyObject * args )
928 {
929         PyObject *newdrawc = NULL, *neweventc = NULL, *newbuttonc = NULL;
930         SpaceScript *sc;
931         Script *script;
932         int startspace = 0;
933
934         if (G.background) {
935                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
936                                               "Can't run Draw.Register() in background mode." );
937         }
938         
939         if( !PyArg_ParseTuple
940             ( args, "O|OO", &newdrawc, &neweventc, &newbuttonc ) )
941                 return EXPP_ReturnPyObjError( PyExc_TypeError,
942                                               "expected one or three PyObjects" );
943
944         if( !PyCallable_Check( newdrawc ) )
945                 newdrawc = NULL;
946         if( !PyCallable_Check( neweventc ) )
947                 neweventc = NULL;
948         if( !PyCallable_Check( newbuttonc ) )
949                 newbuttonc = NULL;
950
951         if( !( newdrawc || neweventc || newbuttonc ) )
952                 Py_RETURN_NONE;
953
954         startspace = curarea->spacetype;
955
956         /* first make sure the current area is of type SPACE_SCRIPT */
957         if( startspace != SPACE_SCRIPT )
958                 newspace( curarea, SPACE_SCRIPT );
959
960         sc = curarea->spacedata.first;
961
962         /* There are two kinds of scripts:
963          * a) those that simply run, finish and return control to Blender;
964          * b) those that do like 'a)' above but leave callbacks for drawing,
965          * events and button events, with this Method_Register (Draw.Register
966          * in Python).  These callbacks are called by scriptspaces (Scripts windows).
967          *
968          * We need to flag scripts that leave callbacks so their namespaces are
969          * not deleted when they 'finish' execution, because the callbacks will
970          * still need the namespace.
971          */
972
973         /* Let's see if this is a new script */
974         script = G.main->script.first;
975         while (script) {
976                 if (script->flags & SCRIPT_RUNNING) break;
977                 script = script->id.next;
978         }
979
980         if( !script ) {
981                 /* not new, it's a left callback calling Register again */
982                 script = sc->script;
983                 if( !script ) {
984                         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
985                                 "Draw.Register can't be used inside script links" );
986                 }
987         }
988         else sc->script = script;
989
990         /* Now we have the right script and can set a lock so its namespace can't be
991          * deleted for as long as we need it */
992         script->flags |= SCRIPT_GUI;
993
994         /* save the last space so we can go back to it upon finishing */
995         if( !script->lastspace )
996                 script->lastspace = startspace;
997
998         /* clean the old callbacks */
999         exit_pydraw( sc, 0 );
1000
1001         /* prepare the new ones and insert them */
1002         Py_XINCREF( newdrawc );
1003         Py_XINCREF( neweventc );
1004         Py_XINCREF( newbuttonc );
1005
1006         script->py_draw = newdrawc;
1007         script->py_event = neweventc;
1008         script->py_button = newbuttonc;
1009
1010         scrarea_queue_redraw( sc->area );
1011
1012         Py_RETURN_NONE;
1013 }
1014
1015 static PyObject *Method_Redraw( PyObject * self, PyObject * args )
1016 {
1017         int after = 0;
1018
1019         if (G.background) {
1020                 Py_RETURN_NONE;
1021         }
1022         
1023         if( !PyArg_ParseTuple( args, "|i", &after ) )
1024                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1025                                               "expected int argument (or nothing)" );
1026
1027         if( after )
1028                 addafterqueue( curarea->win, REDRAW, 1 );
1029         else
1030                 scrarea_queue_winredraw( curarea );
1031
1032         Py_RETURN_NONE;
1033 }
1034
1035 static PyObject *Method_Draw( PyObject * self )
1036 {
1037         if (G.background) {
1038                 Py_RETURN_NONE;
1039         }
1040         
1041         /*@ If forced drawing is disable queue a redraw event instead */
1042         if( EXPP_disable_force_draw ) {
1043                 scrarea_queue_winredraw( curarea );
1044                 Py_RETURN_NONE;
1045         }
1046
1047         scrarea_do_windraw( curarea );
1048
1049         screen_swapbuffers(  );
1050
1051         Py_RETURN_NONE;
1052 }
1053
1054 static PyObject *Method_Create( PyObject * self, PyObject * args )
1055 {
1056         Button *but = NULL;
1057         PyObject *val;
1058         char *newstr;
1059
1060         but = newbutton();
1061         /* If this function dosnt sucseed this will need to be deallocated,
1062          * make sure the type is NOT BSTRING_TYPE before deallocing -1 is ok.
1063          * so we dont dealloc with an uninitialized value wich would be bad! */
1064         if ( PyArg_ParseTuple( args, "fff", but->val.asvec, but->val.asvec+1, but->val.asvec+2 ) ) {
1065                 but->type = BVECTOR_TYPE;
1066         
1067         } else if ( PyArg_ParseTuple( args, "O!", &PyFloat_Type, &val ) ) {
1068                 but->val.asfloat = (float)PyFloat_AS_DOUBLE(val);
1069                 but->type = BFLOAT_TYPE;
1070         
1071         } else if ( PyArg_ParseTuple( args, "O!", &PyInt_Type, &val ) ) {
1072                 but->val.asint = (int)PyInt_AS_LONG(val);
1073                 but->type = BINT_TYPE;
1074         
1075         } else if ( PyArg_ParseTuple( args, "s#", &newstr, &but->slen ) ) {
1076                 if (but->slen + 1 > UI_MAX_DRAW_STR) {
1077                         but->type = -1;
1078                         Py_DECREF((PyObject *)but); /* will remove */
1079                         but = NULL;
1080                         PyErr_SetString( PyExc_TypeError, "string is longer then 399 chars");
1081                 } else {
1082                         but->type = BSTRING_TYPE;
1083                         but->val.asstr = MEM_mallocN( but->slen + 1, "button string" );
1084                         BLI_strncpy( but->val.asstr, newstr, but->slen+1 );
1085                 }
1086         
1087         } else {
1088                 but->type = -1;
1089                 Py_DECREF((PyObject *)but); /* will remove */
1090                 but = NULL;
1091                 PyErr_SetString( PyExc_TypeError, "expected string, float, int or 3-float tuple argument" );
1092         }
1093         
1094         if (but != NULL) {
1095                 PyErr_Clear();
1096         }
1097
1098         return (PyObject*) but;
1099 }
1100
1101
1102 static PyObject *Method_UIBlock( PyObject * self, PyObject * args )
1103 {
1104         PyObject *val = NULL;
1105         PyObject *result = NULL;
1106         ListBase listb= {NULL, NULL};
1107         int mouse_exit = 1;
1108
1109         if (G.background) {
1110                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1111                                               "Can't run Draw.UIBlock() in background mode." );
1112         }
1113         
1114         if ( !PyArg_ParseTuple( args, "O|i", &val, &mouse_exit ) || !PyCallable_Check( val ) ) 
1115                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1116                                               "expected 1 python function and an optional int" );
1117
1118         if (uiblock)
1119                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1120               "cannot run more then 1 UIBlock at a time" );
1121
1122         BPy_Set_DrawButtonsList(PyList_New(0));
1123         
1124         mywinset(G.curscreen->mainwin);
1125         uiblock= uiNewBlock(&listb, "numbuts", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
1126         
1127         uiBlockSetFlag(uiblock, UI_BLOCK_LOOP|UI_BLOCK_REDRAW);
1128         result = PyObject_CallObject( val, NULL );
1129         
1130         if (!result) {
1131                 PyErr_Print(  );
1132                 error_pyscript(  );
1133         } else {
1134                 /* copied from do_clever_numbuts in toolbox.c */
1135                 
1136                 /* Clear all events so tooltips work, this is not ideal and
1137                 only needed because calls from the menu still have some events
1138                 left over when do_clever_numbuts is called.
1139                 Calls from keyshortcuts do not have this problem.*/
1140                 ScrArea *sa;
1141                 BWinEvent temp_bevt;
1142                 for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
1143                         if(sa->win) {
1144                                 while( bwin_qread( sa->win, &temp_bevt ) ) {}
1145                         }
1146                         if(sa->headwin) {
1147                                 while( bwin_qread( sa->headwin, &temp_bevt ) ) {}
1148                         }
1149                 }
1150                 /* Done clearing events */
1151                 
1152                 uiBoundsBlock(uiblock, 5);
1153                 uiDoBlocks(&listb, 0, mouse_exit);
1154         }
1155         uiFreeBlocks(&listb);
1156         uiblock = NULL;
1157         BPy_Free_DrawButtonsList(); /*clear all temp button references*/
1158         
1159         Py_XDECREF( result );
1160         Py_RETURN_NONE;
1161 }
1162
1163 #if 0 /* not used yet */
1164 static void Set_uiBlock(uiBlock *block)
1165 {
1166         uiblock = block;
1167 }
1168 #endif
1169
1170 static uiBlock *Get_uiBlock( void )
1171 {
1172         char butblock[32];
1173         /* Global, used now for UIBlock */
1174         if (uiblock) {
1175                 return uiblock;
1176         }
1177         /* Local */
1178         sprintf( butblock, "win %d", curarea->win );
1179
1180         return uiGetBlock( butblock, curarea );
1181 }
1182
1183
1184 /* We restrict the acceptable event numbers to a proper "free" range
1185  * according to other spaces in Blender.
1186  * winqread***space() (space events callbacks) use short for events
1187  * (called 'val' there) and we also translate by EXPP_BUTTON_EVENTS_OFFSET
1188  * to get rid of unwanted events (check BPY_do_pywin_events above for
1189  * explanation). This function takes care of that and proper checking: */
1190 static int check_button_event(int *event) {
1191         if ((*event < EXPP_BUTTON_EVENTS_MIN) ||
1192                         (*event > EXPP_BUTTON_EVENTS_MAX)) {
1193                 return -1;
1194         }
1195         if (uiblock==NULL) /* For UIBlock we need non offset UI elements */
1196                 *event += EXPP_BUTTON_EVENTS_OFFSET;
1197         return 0;
1198 }
1199
1200 static PyObject *Method_BeginAlign( PyObject * self, PyObject * args )
1201 {
1202         uiBlock *block = Get_uiBlock(  );
1203         
1204         if (block)
1205                 uiBlockBeginAlign(block);
1206         
1207         Py_RETURN_NONE;
1208 }
1209
1210 static PyObject *Method_EndAlign( PyObject * self, PyObject * args )
1211 {
1212         uiBlock *block = Get_uiBlock(  );
1213         
1214         if (block)
1215                 uiBlockEndAlign(block);
1216         
1217         Py_RETURN_NONE;
1218 }
1219
1220 static PyObject *Method_Button( PyObject * self, PyObject * args )
1221 {
1222         uiBlock *block;
1223         char *name, *tip = NULL;
1224         int event;
1225         int x, y, w, h;
1226         PyObject *callback=NULL;
1227
1228         if (G.background) {
1229                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1230                                               "Can't run Draw.Button() in background mode." );
1231         }
1232         
1233         if( !PyArg_ParseTuple( args, "siiiii|sO", &name, &event,
1234                                &x, &y, &w, &h, &tip, &callback ) )
1235                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1236                                               "expected a string, five ints and optionally string and callback arguments" );
1237
1238         UI_METHOD_ERRORCHECK;
1239
1240         block = Get_uiBlock(  );
1241         if( block ) {
1242                 uiBut *ubut = uiDefBut( block, BUT, event, name, (short)x, (short)y, (short)w, (short)h, 0, 0, 0, 0, 0, tip );
1243                 set_pycallback(ubut, callback, NULL);
1244         }
1245         Py_RETURN_NONE;
1246 }
1247
1248 static PyObject *Method_Menu( PyObject * self, PyObject * args )
1249 {
1250         uiBlock *block;
1251         char *name, *tip = NULL;
1252         int event, def;
1253         int x, y, w, h;
1254         Button *but;
1255         PyObject *callback=NULL;
1256
1257         if (G.background) {
1258                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1259                                               "Can't run Draw.Menu() in background mode." );
1260         }
1261         
1262         if( !PyArg_ParseTuple( args, "siiiiii|sO", &name, &event,
1263                                &x, &y, &w, &h, &def, &tip, &callback ) )
1264                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1265                                               "expected a string, six ints and optionally string and callback arguments" );
1266
1267         UI_METHOD_ERRORCHECK;
1268         
1269         but = newbutton(  );
1270         but->type = BINT_TYPE;
1271         but->val.asint = def;
1272         if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
1273         
1274         block = Get_uiBlock(  );
1275         if( block ) {
1276                 uiBut *ubut = uiDefButI( block, MENU, event, name, (short)x, (short)y, (short)w, (short)h,
1277                            &but->val.asint, 0, 0, 0, 0, but->tooltip );
1278                 set_pycallback(ubut, callback, but);
1279         }
1280         return ( PyObject * ) but;
1281 }
1282
1283 static PyObject *Method_Toggle( PyObject * self, PyObject * args )
1284 {
1285         uiBlock *block;
1286         char *name, *tip = NULL;
1287         int event;
1288         int x, y, w, h, def;
1289         Button *but;
1290         PyObject *callback=NULL;
1291
1292         if (G.background) {
1293                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1294                                               "Can't run Draw.Toggle() in background mode." );
1295         }
1296         
1297         if( !PyArg_ParseTuple( args, "siiiiii|sO", &name, &event,
1298                                &x, &y, &w, &h, &def, &tip, &callback ) )
1299                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1300                                               "expected a string, six ints and optionally string and callback arguments" );
1301
1302         UI_METHOD_ERRORCHECK;
1303         
1304         but = newbutton(  );
1305         but->type = BINT_TYPE;
1306         but->val.asint = def;
1307         if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
1308         
1309         block = Get_uiBlock(  );
1310         if( block ) {
1311                 uiBut *ubut = uiDefButI( block, TOG, event, name, (short)x, (short)y, (short)w, (short)h,
1312                            &but->val.asint, 0, 0, 0, 0, but->tooltip );
1313                 set_pycallback(ubut, callback, but);
1314         }
1315         return ( PyObject * ) but;
1316 }
1317
1318 /*@DO NOT TOUCH THIS FUNCTION !
1319          Redrawing a slider inside its own callback routine is actually forbidden
1320          with the current toolkit architecture (button routines are not reentrant).
1321          But it works anyway.
1322          XXX This is condemned to be dinosource in future - it's a hack.
1323          */
1324
1325 static void py_slider_update( void *butv, void *data2_unused )
1326 {
1327         uiBut *but = butv;
1328         PyObject *ref = Py_BuildValue( "(i)", SPACE_VIEW3D );
1329         PyObject *ret = NULL;
1330
1331         EXPP_disable_force_draw = 1;
1332         /*@ Disable forced drawing, otherwise the button object which
1333          * is still being used might be deleted */
1334
1335         curarea->win_swap = WIN_BACK_OK;
1336         /* removed global uiFrontBuf (contact ton when this goes wrong here) */
1337
1338         disable_where_script( 1 );
1339
1340         spacescript_do_pywin_buttons( curarea->spacedata.first,
1341                 (unsigned short)uiButGetRetVal( but ) -  EXPP_BUTTON_EVENTS_OFFSET );
1342
1343         /* XXX useless right now, investigate better before a bcon 5 */
1344         ret = M_Window_Redraw( 0, ref );
1345
1346         Py_XDECREF(ref);
1347         Py_XDECREF(ret);
1348
1349         disable_where_script( 0 );
1350
1351         EXPP_disable_force_draw = 0;
1352 }
1353
1354 static PyObject *Method_Slider( PyObject * self, PyObject * args )
1355 {
1356         uiBlock *block;
1357         char *name, *tip = NULL;
1358         int event;
1359         int x, y, w, h, realtime = 1;
1360         Button *but;
1361         PyObject *mino, *maxo, *inio;
1362         PyObject *callback=NULL;
1363
1364         if (G.background) {
1365                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1366                                               "Can't run Draw.Sider() in background mode." );
1367         }
1368         
1369         if( !PyArg_ParseTuple( args, "siiiiiOOO|isO", &name, &event,
1370                                &x, &y, &w, &h, &inio, &mino, &maxo, &realtime,
1371                                &tip, &callback ) )
1372                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1373                                               "expected a string, five ints, three PyObjects\n\
1374                         and optionally int, string and callback arguments" );
1375
1376         if(realtime && uiblock)
1377                 realtime = 0; /* realtime dosnt work with UIBlock */
1378
1379         UI_METHOD_ERRORCHECK;
1380         
1381         but = newbutton(  );
1382
1383         if( PyFloat_Check( inio ) ) {
1384                 float ini, min, max;
1385
1386                 ini = (float)PyFloat_AsDouble( inio );
1387                 min = (float)PyFloat_AsDouble( mino );
1388                 max = (float)PyFloat_AsDouble( maxo );
1389
1390                 but->type = BFLOAT_TYPE;
1391                 but->val.asfloat = ini;
1392                 if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
1393                 
1394                 block = Get_uiBlock(  );
1395                 if( block ) {
1396                         uiBut *ubut;
1397                         ubut = uiDefButF( block, NUMSLI, event, name, (short)x, (short)y, (short)w,
1398                                           (short)h, &but->val.asfloat, min, max, 0, 0,
1399                                           but->tooltip );
1400                         if( realtime )
1401                                 uiButSetFunc( ubut, py_slider_update, ubut, NULL );
1402                         else
1403                                 set_pycallback(ubut, callback, but);
1404                 }
1405         } else {
1406                 int ini, min, max;
1407
1408                 ini = PyInt_AsLong( inio );
1409                 min = PyInt_AsLong( mino );
1410                 max = PyInt_AsLong( maxo );
1411
1412                 but->type = BINT_TYPE;
1413                 but->val.asint = ini;
1414                 if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
1415                 
1416                 block = Get_uiBlock(  );
1417                 if( block ) {
1418                         uiBut *ubut;
1419                         ubut = uiDefButI( block, NUMSLI, event, name, (short)x, (short)y, (short)w,
1420                                           (short)h, &but->val.asint, (float)min, (float)max, 0, 0,
1421                                           but->tooltip );
1422                         if( realtime )
1423                                 uiButSetFunc( ubut, py_slider_update, ubut, NULL );
1424                         else
1425                                 set_pycallback(ubut, callback, but);
1426                 }
1427         }
1428         return ( PyObject * ) but;
1429 }
1430
1431 static PyObject *Method_Scrollbar( PyObject * self, PyObject * args )
1432 {
1433         char *tip = NULL;
1434         uiBlock *block;
1435         int event;
1436         int x, y, w, h, realtime = 1;
1437         Button *but;
1438         PyObject *mino, *maxo, *inio;
1439         float ini, min, max;
1440         uiBut *ubut;
1441         
1442         if (G.background) {
1443                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1444                                               "Can't run Draw.Scrollbar() in background mode." );
1445         }
1446         
1447         if( !PyArg_ParseTuple( args, "iiiiiOOO|isO", &event, &x, &y, &w, &h,
1448                                &inio, &mino, &maxo, &realtime, &tip ) )
1449                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1450                         "expected five ints, three PyObjects and optionally\n\
1451 another int and string as arguments" );
1452
1453         if( !PyNumber_Check( inio ) || !PyNumber_Check( inio )
1454             || !PyNumber_Check( inio ) )
1455                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1456                                               "expected numbers for initial, min, and max" );
1457
1458         if (check_button_event(&event) == -1)
1459         return EXPP_ReturnPyObjError( PyExc_AttributeError,
1460                 "button event argument must be in the range [0, 16382]");
1461
1462         but = newbutton(  );
1463         if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
1464         
1465         if( PyFloat_Check( inio ) )
1466                 but->type = BFLOAT_TYPE;
1467         else
1468                 but->type = BINT_TYPE;
1469
1470         ini = (float)PyFloat_AsDouble( inio );
1471         min = (float)PyFloat_AsDouble( mino );
1472         max = (float)PyFloat_AsDouble( maxo );
1473         
1474         block = Get_uiBlock(  );
1475
1476         if( block ) {
1477                 if( but->type == BFLOAT_TYPE ) {
1478                         but->val.asfloat = ini;
1479                         ubut = uiDefButF( block, SCROLL, event, "", (short)x, (short)y, (short)w, (short)h,
1480                                           &but->val.asfloat, min, max, 0, 0, but->tooltip );
1481                         if( realtime )
1482                                 uiButSetFunc( ubut, py_slider_update, ubut, NULL );
1483                 } else {
1484                         but->val.asint = (int)ini;
1485                         ubut = uiDefButI( block, SCROLL, event, "", (short)x, (short)y, (short)w, (short)h,
1486                                           &but->val.asint, min, max, 0, 0, but->tooltip );
1487                         if( realtime )
1488                                 uiButSetFunc( ubut, py_slider_update, ubut, NULL );
1489                 }
1490         }
1491         return ( PyObject * ) but;
1492 }
1493
1494 static PyObject *Method_ColorPicker( PyObject * self, PyObject * args )
1495 {
1496         char USAGE_ERROR[] = "expected a 3-float tuple of values between 0 and 1";
1497         Button *but;
1498         PyObject *inio;
1499         uiBlock *block;
1500         char *tip = NULL;
1501         float col[3];
1502         int event;
1503         short x, y, w, h;
1504         PyObject *callback=NULL;
1505         
1506         if (G.background) {
1507                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1508                                               "Can't run Draw.ColorPicker() in background mode." );
1509         }
1510         
1511         if( !PyArg_ParseTuple( args, "ihhhhO!|sO", &event,
1512                                &x, &y, &w, &h, &PyTuple_Type, &inio, &tip, &callback ) )
1513                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1514                                               "expected five ints, one tuple and optionally string and callback arguments" );
1515  
1516         UI_METHOD_ERRORCHECK;
1517  
1518         if ( !PyArg_ParseTuple( inio, "fff", col, col+1, col+2 ) )
1519                 return EXPP_ReturnPyObjError( PyExc_ValueError, USAGE_ERROR);
1520
1521         if      (       col[0] < 0 || col[0] > 1
1522                 ||      col[1] < 0 || col[1] > 1
1523                 ||      col[2] < 0 || col[2] > 1 )
1524                 return EXPP_ReturnPyObjError( PyExc_ValueError, USAGE_ERROR);
1525
1526         if ( EXPP_check_sequence_consistency( inio, &PyFloat_Type ) != 1 )
1527                 return EXPP_ReturnPyObjError( PyExc_ValueError, USAGE_ERROR);
1528  
1529         but = newbutton();
1530  
1531         but->type = BVECTOR_TYPE;
1532         but->val.asvec[0] = col[0];
1533         but->val.asvec[1] = col[1];
1534         but->val.asvec[2] = col[2];
1535         if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
1536         
1537         block = Get_uiBlock(  );
1538         if( block ) {
1539                 uiBut *ubut;
1540                 ubut = uiDefButF( block, COL, event, "", x, y, w, h, but->val.asvec, 0, 0, 0, 0, but->tooltip);
1541                 set_pycallback(ubut, callback, but);
1542         }
1543
1544         return ( PyObject * ) but;
1545 }
1546
1547
1548
1549 static PyObject *Method_Normal( PyObject * self, PyObject * args )
1550 {
1551         char USAGE_ERROR[] = "expected a 3-float tuple of values between -1 and 1";
1552         Button *but;
1553         PyObject *inio;
1554         uiBlock *block;
1555         char *tip = NULL;
1556         float nor[3];
1557         int event;
1558         short x, y, w, h;
1559         PyObject *callback=NULL;
1560         
1561         if (G.background) {
1562                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1563                                               "Can't run Draw.Normal() in background mode." );
1564         }
1565         
1566         if( !PyArg_ParseTuple( args, "ihhhhO!|sO", &event,
1567                                &x, &y, &w, &h, &PyTuple_Type, &inio, &tip, &callback ) )
1568                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1569                                               "expected five ints, one tuple and optionally string and callback arguments" );
1570  
1571         UI_METHOD_ERRORCHECK;
1572  
1573         if ( !PyArg_ParseTuple( inio, "fff", nor, nor+1, nor+2 ) )
1574                 return EXPP_ReturnPyObjError( PyExc_ValueError, USAGE_ERROR);
1575
1576         if ( EXPP_check_sequence_consistency( inio, &PyFloat_Type ) != 1 )
1577                 return EXPP_ReturnPyObjError( PyExc_ValueError, USAGE_ERROR);
1578  
1579         but = newbutton();
1580         if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
1581         
1582         but->type = BVECTOR_TYPE;
1583         but->val.asvec[0] = nor[0];
1584         but->val.asvec[1] = nor[1];
1585         but->val.asvec[2] = nor[2];
1586         
1587         block = Get_uiBlock(  );
1588         if( block ) {
1589                 uiBut *ubut;
1590                 ubut = uiDefButF( block, BUT_NORMAL, event, "", x, y, w, h, but->val.asvec, 0.0f, 1.0f, 0, 0, but->tooltip);
1591                 set_pycallback(ubut, callback, but);
1592         }
1593         
1594         return ( PyObject * ) but;
1595 }
1596
1597 static PyObject *Method_Number( PyObject * self, PyObject * args )
1598 {
1599         uiBlock *block;
1600         char *name, *tip = NULL;
1601         int event;
1602         int x, y, w, h;
1603         Button *but;
1604         PyObject *mino, *maxo, *inio;
1605         PyObject *callback=NULL;
1606         PyObject *a1=NULL;
1607         PyObject *a2=NULL;
1608         uiBut *ubut= NULL;
1609         
1610         if (G.background) {
1611                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1612                                               "Can't run Draw.Number() in background mode." );
1613         }
1614         
1615         if( !PyArg_ParseTuple( args, "siiiiiOOO|sOOO", &name, &event,
1616                                &x, &y, &w, &h, &inio, &mino, &maxo, &tip, &callback, &a1, &a2 ) )
1617                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1618                                               "expected a string, five ints, three PyObjects and\n\
1619                         optionally string, callback, range and precision arguments" );
1620
1621         UI_METHOD_ERRORCHECK;
1622
1623         if ( !PyNumber_Check(inio) || !PyNumber_Check(mino) ||
1624                         !PyNumber_Check(maxo) ) {
1625                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1626                                 "expected ints or floats for the initial, min and max values" );
1627         }
1628
1629         but = newbutton(  );
1630         if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
1631         block = Get_uiBlock(  );
1632         
1633         if( PyFloat_Check( inio ) ) {
1634                 float ini, min, max, range, precission=0;
1635
1636                 ini = (float)PyFloat_AsDouble( inio );
1637                 min = (float)PyFloat_AsDouble( mino );
1638                 max = (float)PyFloat_AsDouble( maxo );
1639                 
1640                 if(a1 && PyNumber_Check(a1)) {
1641                         if(PyFloat_Check(a1))
1642                                 range= (float)PyFloat_AsDouble(a1);
1643                         else
1644                                 range= (float)PyInt_AsLong(a1);
1645                 } else {
1646                         range= (float)fabs(max-min); /* Click step will be a 10th of the range. */
1647                         if (!range) range= 1.0f; /* avoid any odd errors */
1648                 }
1649                 
1650                 if(a2 && PyNumber_Check(a2)) {
1651                         if(PyFloat_Check(a2))
1652                                 precission= (float)PyFloat_AsDouble(a2);
1653                         else
1654                                 precission= (float)PyInt_AsLong(a2);
1655                 } else {
1656                         /* set the precission to display*/
1657                         if      (range>=1000.0f) precission=1.0f;
1658                         else if (range>=100.0f) precission=2.0f;
1659                         else if (range>=10.0f) precission=3.0f;
1660                         else precission=4.0f;
1661                         
1662                         range *= 10;
1663                 }
1664                         
1665                 but->type = BFLOAT_TYPE;
1666                 but->val.asfloat = ini;
1667
1668                 
1669                 if( block )
1670                         ubut= uiDefButF( block, NUM, event, name, (short)x, (short)y, (short)w, (short)h,
1671                                    &but->val.asfloat, min, max, range, precission, but->tooltip );
1672         } else {
1673                 int ini, min, max;
1674
1675                 ini = PyInt_AsLong( inio );
1676                 min = PyInt_AsLong( mino );
1677                 max = PyInt_AsLong( maxo );
1678
1679                 but->type = BINT_TYPE;
1680                 but->val.asint = ini;
1681
1682                 if( block )
1683                         ubut= uiDefButI( block, NUM, event, name, (short)x, (short)y, (short)w, (short)h,
1684                                    &but->val.asint, (float)min, (float)max, 0, 0, but->tooltip );
1685         }
1686         
1687         if (ubut) set_pycallback(ubut, callback, but);
1688         
1689         return ( PyObject * ) but;
1690 }
1691
1692 static PyObject *Method_String( PyObject * self, PyObject * args )
1693 {
1694         uiBlock *block;
1695         char *info_arg = NULL, *tip = NULL, *newstr = NULL;
1696         char *info_str = NULL, *info_str0 = " ";
1697         int event;
1698         int x, y, w, h, len, real_len = 0;
1699         Button *but;
1700         PyObject *callback=NULL;
1701
1702         if (G.background) {
1703                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1704                                               "Can't run Draw.String() in background mode." );
1705         }
1706         
1707         if( !PyArg_ParseTuple( args, "siiiiisi|sO", &info_arg, &event,
1708                         &x, &y, &w, &h, &newstr, &len, &tip, &callback ) )
1709                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1710                         "expected a string, five ints, a string, an int and\n\
1711         optionally string and callback arguments" );
1712
1713         UI_METHOD_ERRORCHECK;
1714
1715         if (len > (UI_MAX_DRAW_STR - 1))
1716                 return EXPP_ReturnPyObjError( PyExc_ValueError,
1717                         "The maximum length of a string is 399, your value is too high.");
1718
1719         real_len = strlen(newstr);
1720         if (real_len > len) real_len = len;
1721         
1722         but = newbutton(  );
1723         but->type = BSTRING_TYPE;
1724         but->slen = len;
1725         but->val.asstr = MEM_mallocN( len + 1, "pybutton str" );
1726         if (tip) strncpy(but->tooltip, tip, BPY_MAX_TOOLTIP);
1727
1728         BLI_strncpy( but->val.asstr, newstr, len + 1); /* adds '\0' */
1729         but->val.asstr[real_len] = '\0';
1730
1731         if (info_arg[0] == '\0') info_str = info_str0;
1732         else info_str = info_arg;
1733
1734         block = Get_uiBlock(  );
1735         if( block ) {
1736                 uiBut *ubut = uiDefBut( block, TEX, event, info_str, (short)x, (short)y, (short)w, (short)h,
1737                           but->val.asstr, 0, (float)len, 0, 0, but->tooltip );
1738                 set_pycallback(ubut, callback, but);
1739         }
1740         return ( PyObject * ) but;
1741 }
1742
1743 static PyObject *Method_GetStringWidth( PyObject * self, PyObject * args )
1744 {
1745         char *text;
1746         char *font_str = "normal";
1747         struct BMF_Font *font;
1748         PyObject *width;
1749
1750         if( !PyArg_ParseTuple( args, "s|s", &text, &font_str ) )
1751                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1752                                               "expected one or two string arguments" );
1753
1754         if( !strcmp( font_str, "normal" ) )
1755                 font = ( &G )->font;
1756         else if( !strcmp( font_str, "normalfix" ) )
1757                 font = BMF_GetFont(BMF_kScreen12);
1758         else if( !strcmp( font_str, "large" ) )
1759                 font = BMF_GetFont(BMF_kScreen15);
1760         else if( !strcmp( font_str, "small" ) )
1761                 font = ( &G )->fonts;
1762         else if( !strcmp( font_str, "tiny" ) )
1763                 font = ( &G )->fontss;
1764         else
1765                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1766                                               "\"font\" must be: 'large','normal' (default), 'normalfix', 'small' or 'tiny'." );
1767
1768         width = PyInt_FromLong( BMF_GetStringWidth( font, text ) );
1769
1770         if( !width )
1771                 return EXPP_ReturnPyObjError( PyExc_MemoryError,
1772                                               "couldn't create PyInt" );
1773
1774         return width;
1775 }
1776
1777 static PyObject *Method_Text( PyObject * self, PyObject * args )
1778 {
1779         char *text;
1780         char *font_str = NULL;
1781         struct BMF_Font *font;
1782
1783         if (G.background) {
1784                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1785                                               "Can't run Draw.Text() in background mode." );
1786         }
1787         
1788         if( !PyArg_ParseTuple( args, "s|s", &text, &font_str ) )
1789                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1790                                               "expected one or two string arguments" );
1791
1792         if( !font_str )
1793                 font = ( &G )->font;
1794         else if( !strcmp( font_str, "large" ) )
1795                 font = BMF_GetFont(BMF_kScreen15);
1796         else if( !strcmp( font_str, "normalfix" ) )
1797                 font = BMF_GetFont(BMF_kScreen12);
1798         else if( !strcmp( font_str, "normal" ) )
1799                 font = ( &G )->font;
1800         else if( !strcmp( font_str, "small" ) )
1801                 font = ( &G )->fonts;
1802         else if( !strcmp( font_str, "tiny" ) )
1803                 font = ( &G )->fontss;
1804         else
1805                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1806                                               "\"font\" must be: 'large','normal' (default), 'normalfix', 'small' or 'tiny'." );
1807
1808         BMF_DrawString( font, text );
1809
1810         return PyInt_FromLong( BMF_GetStringWidth( font, text ) );
1811 }
1812
1813 static PyObject *Method_Label( PyObject * self, PyObject * args )
1814 {
1815         uiBlock *block;
1816         char *text;
1817         int x, y, w, h;
1818
1819         if (G.background) {
1820                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1821                                               "Can't run Draw.Label() in background mode." );
1822         }
1823         
1824         if( !PyArg_ParseTuple( args, "siiii", &text, &x, &y, &w, &h ) )
1825                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1826                         "expected a string and four ints" );
1827
1828         block = Get_uiBlock(  );
1829         uiDefBut(block, LABEL, 0, text, x, y, w, h, 0, 0, 0, 0, 0, "");
1830         
1831         Py_RETURN_NONE;
1832 }
1833
1834
1835 static PyObject *Method_PupMenu( PyObject * self, PyObject * args )
1836 {
1837         char *text;
1838         int maxrow = -1;
1839         PyObject *ret;
1840         
1841         if (G.background) {
1842                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1843                                               "Can't run Draw.PupMenu() in background mode." );
1844         }
1845         
1846         if( !PyArg_ParseTuple( args, "s|i", &text, &maxrow ) )
1847                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1848                                               "expected a string and optionally an int as arguments" );
1849
1850         if( maxrow >= 0 )
1851                 ret = PyInt_FromLong( pupmenu_col( text, maxrow ) );
1852         else
1853                 ret = PyInt_FromLong( pupmenu( text ) );
1854
1855         if( ret )
1856                 return ret;
1857
1858         return EXPP_ReturnPyObjError( PyExc_MemoryError,
1859                                       "couldn't create a PyInt" );
1860 }
1861
1862 static int current_menu_ret;
1863 static void toolbox_event(void *arg, int event)
1864 {
1865         current_menu_ret = event;
1866 }
1867
1868 static TBitem * menu_from_pylist( PyObject * current_menu, ListBase *storage )
1869 {
1870         TBitem *tbarray, *tbitem;
1871         Link *link;
1872         PyObject *item, *submenu;
1873         int size, i;
1874         
1875         char *menutext;
1876         int event;
1877         
1878         size = PyList_Size( current_menu );
1879         
1880         link= MEM_callocN(sizeof(Link) + sizeof(TBitem)*(size+1), "python menu");
1881         
1882         if (link==NULL) {
1883                 PyErr_SetString( PyExc_MemoryError, "Could not allocate enough memory for the menu" );
1884                 BLI_freelistN(storage);
1885                 return NULL;
1886         }
1887         
1888         BLI_addtail(storage, link);
1889         
1890         tbarray = tbitem = (TBitem *)(link+1);
1891         
1892         for (i=0; i<size; i++, tbitem++) {
1893                 /* need to get these in */
1894                 item = PyList_GET_ITEM( current_menu, i);
1895                 
1896                 if (item == Py_None) {
1897                         tbitem->name = "SEPR";
1898                 } else if( PyArg_ParseTuple( item, "si", &menutext, &event ) ) {
1899                         tbitem->name = menutext;
1900                         tbitem->retval = event;
1901                         //current_menu_index
1902                 } else if( PyArg_ParseTuple( item, "sO!", &menutext, &PyList_Type, &submenu ) ) {
1903                         PyErr_Clear(); /* from PyArg_ParseTuple above */
1904                         tbitem->name = menutext;
1905                         tbitem->poin = menu_from_pylist(submenu, storage);
1906                         if (tbitem->poin == NULL) {
1907                                 BLI_freelistN(storage);
1908                                 return NULL; /* error should be set */
1909                         }
1910                 } else {
1911                         PyErr_Clear(); /* from PyArg_ParseTuple above */
1912                         
1913                         PyErr_SetString( PyExc_TypeError, "Expected a list of name,event tuples, None, or lists for submenus" );
1914                         BLI_freelistN(storage);
1915                         return NULL;
1916                 }
1917         }
1918         tbitem->icon= -1;       /* end signal */
1919         tbitem->name= "";
1920         tbitem->retval= 0;
1921         tbitem->poin= toolbox_event;
1922         
1923         return tbarray;
1924 }
1925
1926 static PyObject *Method_PupTreeMenu( PyObject * self, PyObject * args )
1927 {
1928         PyObject * current_menu;
1929         ListBase storage = {NULL, NULL};
1930         TBitem *tb;
1931         
1932         if (G.background) {
1933                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1934                                               "Can't run Draw.PupMenuTree() in background mode." );
1935         }
1936         
1937         if( !PyArg_ParseTuple( args, "O!", &PyList_Type, &current_menu ) )
1938                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1939                         "Expected a list" );
1940         
1941         mywinset(G.curscreen->mainwin); // we go to screenspace
1942         
1943         tb = menu_from_pylist(current_menu, &storage);
1944         
1945         if (!tb) { 
1946                 /* Error is set */
1947                 return NULL; 
1948         }
1949         
1950         current_menu_ret = -1;
1951         toolbox_generic(tb);
1952         
1953         /* free all dynamic entries... */
1954         BLI_freelistN(&storage);
1955         
1956         mywinset(curarea->win);
1957         return PyInt_FromLong( current_menu_ret ); /* current_menu_ret is set by toolbox_event callback */
1958 }
1959
1960 static PyObject *Method_PupIntInput( PyObject * self, PyObject * args )
1961 {
1962         char *text = NULL;
1963         int min = 0, max = 1;
1964         short var = 0;
1965         PyObject *ret = NULL;
1966
1967         if (G.background) {
1968                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1969                                               "Can't run Draw.PupIntInput() in background mode." );
1970         }
1971         
1972         if( !PyArg_ParseTuple( args, "s|hii", &text, &var, &min, &max ) )
1973                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1974                                               "expected 1 string and 3 int arguments" );
1975
1976         if( button( &var, (short)min, (short)max, text ) == 0 ) {
1977                 Py_INCREF( Py_None );
1978                 return Py_None;
1979         }
1980         ret = PyInt_FromLong( var );
1981         if( ret )
1982                 return ret;
1983
1984         return EXPP_ReturnPyObjError( PyExc_MemoryError,
1985                                       "couldn't create a PyInt" );
1986 }
1987
1988 static PyObject *Method_PupFloatInput( PyObject * self, PyObject * args )
1989 {
1990         char *text = NULL;
1991         float min = 0, max = 1, var = 0, a1 = 10, a2 = 2;
1992         PyObject *ret = NULL;
1993
1994         if (G.background) {
1995                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1996                                               "Can't run Draw.PupFloatInput() in background mode." );
1997         }
1998         
1999         if( !PyArg_ParseTuple
2000             ( args, "s|fffff", &text, &var, &min, &max, &a1, &a2 ) )
2001                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2002                                               "expected 1 string and 5 float arguments" );
2003
2004         if( fbutton( &var, min, max, a1, a2, text ) == 0 ) {
2005                 Py_INCREF( Py_None );
2006                 return Py_None;
2007         }
2008         ret = PyFloat_FromDouble( var );
2009         if( ret )
2010                 return ret;
2011
2012         return EXPP_ReturnPyObjError( PyExc_MemoryError,
2013                                       "couldn't create a PyFloat" );
2014 }
2015
2016 static PyObject *Method_PupStrInput( PyObject * self, PyObject * args )
2017 {
2018         char *text = NULL, *textMsg = NULL;
2019         char tmp[101];
2020         char max = 20;
2021         PyObject *ret = NULL;
2022
2023         if (G.background) {
2024                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2025                                               "Can't run Draw.PupStrInput() in background mode." );
2026         }
2027         
2028         if( !PyArg_ParseTuple( args, "ss|b", &textMsg, &text, &max ) )
2029                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2030                                               "expected 2 strings and 1 int" );
2031
2032         if( ( max <= 0 ) || ( max > 100 ) )
2033                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
2034                                               "max string length value must be in the range [1, 100]." );
2035
2036         /* copying the text string handles both cases:
2037          * max < strlen(text) (by truncating) and
2038          * max > strlen(text) (by expanding to strlen(tmp)) */
2039         BLI_strncpy( tmp, text, max + 1 );
2040
2041         if( sbutton( tmp, 0, max, textMsg ) == 0 ) {
2042                 Py_INCREF( Py_None );
2043                 return Py_None;
2044         }
2045
2046         ret = PyString_FromString( tmp );
2047
2048         if( ret )
2049                 return ret;
2050
2051         return EXPP_ReturnPyObjError( PyExc_MemoryError,
2052                                       "couldn't create a PyString" );
2053 }
2054
2055 static PyObject *Method_PupBlock( PyObject * self, PyObject * args )
2056 {
2057         PyObject *pyList, *pyItem;
2058         float min, max;
2059         int len, i;
2060         char *title;
2061
2062         if (G.background) {
2063                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2064                                               "Can't run Draw.PupBlock() in background mode." );
2065         }
2066         
2067         if (!PyArg_ParseTuple( args, "sO", &title, &pyList ) || !PySequence_Check( pyList ))
2068                 return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and a sequence" );
2069
2070
2071         len = PySequence_Length(pyList);
2072
2073         if (len == 0)
2074                 return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string and a non-empty sequence." );
2075
2076         if (len > 120) /* LIMIT DEFINED IN toolbox.c    */
2077                 return EXPP_ReturnPyObjError( PyExc_ValueError, "sequence cannot have more than 120 elements" );
2078
2079         for ( i=0 ; i<len ; i++ ) {
2080                 PyObject *pyMin = NULL, *pyMax = NULL;
2081                 PyObject *f1, *f2;
2082                 Button *but = NULL;
2083                 int tlen;
2084                 char *text, *tip = NULL;
2085
2086                 pyItem = PySequence_GetItem( pyList, i );
2087                 if (!pyItem)
2088                         return NULL;
2089
2090                 if (PyString_Check( pyItem )) {
2091                         tlen = -2;      /* single string for label, giving it a special len for later */
2092                 }
2093                 else if (PyTuple_Check( pyItem )) {
2094                         /* tuple for other button, get the length for later */
2095                         tlen = PyTuple_Size( pyItem );
2096                 }
2097                 else {
2098                         /* Neither a string or a tuple, error */
2099                         Py_DECREF( pyItem );
2100                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string or a tuple containing 2 to 5 values." );
2101                 }
2102
2103                 switch (tlen) {
2104                 case -2:                /*      LABEL   */
2105                         text = PyString_AsString( pyItem );
2106                         add_numbut(i, LABEL, text, 0, 0, NULL, NULL);
2107                         break;
2108                 case 2:         /*      TOGGLE  (no tooltip)    */
2109                 case 3:         /*      TOGGLE  */
2110                         if (!PyArg_ParseTuple( pyItem, "sO!|s", &text, &Button_Type, &but, &tip )) {
2111                                 Py_DECREF( pyItem );
2112                                 return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a tuple containing a string, a Button object and optionally a string for toggles" );
2113                         }
2114
2115                         if (but->type != BINT_TYPE) {
2116                                 Py_DECREF( pyItem );
2117                                 return EXPP_ReturnPyObjError( PyExc_ValueError, "Button object for toggles should hold an integer" );
2118                         }
2119
2120                         add_numbut(i, TOG|INT, text, 0, 0, &but->val.asint, tip);
2121                         break;
2122                 case 4:         /*      TEX and NUM (no tooltip)        */
2123                 case 5:         /*      TEX and NUM     */
2124                         if (!PyArg_ParseTuple( pyItem, "sO!OO|s", &text, &Button_Type, &but, &pyMin, &pyMax, &tip )) {
2125                                 Py_DECREF( pyItem );
2126                                 return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a tuple containing a string, a Button object, two numerical values and optionally a string for Text and Num buttons" );
2127                         }
2128
2129                         f1 = PyNumber_Float(pyMin);
2130                         f2 = PyNumber_Float(pyMax);
2131
2132                         if (!f1 || !f2) {
2133                                 Py_DECREF( pyItem );
2134                                 return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a tuple containing a string, a Button object, two numerical values and optionally a string for Text and Num buttons" );
2135                         }
2136
2137                         min = (float)PyFloat_AS_DOUBLE(f1);
2138                         max = (float)PyFloat_AS_DOUBLE(f2);
2139                         Py_DECREF( f1 );
2140                         Py_DECREF( f2 );
2141
2142                         switch ( but->type ) {
2143                         case BINT_TYPE:
2144                                 add_numbut(i, NUM|INT, text, min, max, &but->val.asint, tip);
2145                                 break;
2146                         case BFLOAT_TYPE:
2147                                 add_numbut(i, NUM|FLO, text, min, max, &but->val.asfloat, tip);
2148                                 break;
2149                         case BSTRING_TYPE:
2150                                 if (max+1>UI_MAX_DRAW_STR) {
2151                                         Py_DECREF( pyItem );
2152                                         return EXPP_ReturnPyObjError( PyExc_ValueError, "length of a string buttons must be less then 400" );
2153                                 }
2154                                 max = (float)floor(max);
2155
2156                                 if (max > but->slen) {
2157                                         int old_len = but->slen;
2158                                         char *old_str = but->val.asstr;
2159                                         but->slen = (int)max;
2160                                         but->val.asstr = MEM_callocN( but->slen + 1, "button pupblock");
2161                                         BLI_strncpy( but->val.asstr, old_str, old_len + 1 );
2162                                         MEM_freeN(old_str);
2163                                 }
2164
2165                                 add_numbut(i, TEX, text, 0.0f, max, but->val.asstr, tip);
2166                         }
2167
2168                         break;
2169                 default:
2170                         Py_DECREF( pyItem );
2171                         return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string or a tuple containing 2 to 5 values." );
2172                 }
2173                 Py_DECREF( pyItem );
2174         }
2175
2176         if (do_clever_numbuts(title, len, REDRAW))
2177                 return EXPP_incr_ret_True();
2178         else
2179                 return EXPP_incr_ret_False();
2180 }
2181
2182
2183 /*****************************************************************************
2184  * Function:            Method_Image                                         *
2185  * Python equivalent:   Blender.Draw.Image                                   *
2186  *                                                                           *
2187  * @author Jonathan Merritt <j.merritt@pgrad.unimelb.edu.au>                 *
2188  ****************************************************************************/
2189 static PyObject *Method_Image( PyObject * self, PyObject * args )
2190 {
2191         PyObject *pyObjImage;
2192         BPy_Image *py_img;
2193         Image *image;
2194         ImBuf *ibuf;
2195         float originX, originY;
2196         float zoomX = 1.0, zoomY = 1.0;
2197         int clipX = 0, clipY = 0, clipW = -1, clipH = -1;
2198         /*GLfloat scissorBox[4];*/
2199
2200         if (G.background) {
2201                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2202                                               "Can't run Draw.Image() in background mode." );
2203         }
2204         
2205         /* parse the arguments passed-in from Python */
2206         if( !PyArg_ParseTuple( args, "O!ff|ffiiii", &Image_Type, &pyObjImage, 
2207                 &originX, &originY, &zoomX, &zoomY, 
2208                 &clipX, &clipY, &clipW, &clipH ) )
2209                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2210                         "expected a Blender.Image and 2 floats, and " \
2211                         "optionally 2 floats and 4 ints as arguments" );
2212         /* check that the zoom factors are valid */
2213         if( ( zoomX < 0.0 ) || ( zoomY < 0.0 ) )
2214                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2215                         "invalid zoom factors - they must be > 0.0" );
2216         if ((zoomX == 0.0 ) || ( zoomY == 0.0 )) {
2217                 /* sometimes python doubles can be converted from small values to a zero float, in this case just dont draw */
2218                 Py_RETURN_NONE;
2219         }
2220         
2221         
2222         /* fetch a C Image pointer from the passed-in Python object */
2223         py_img = ( BPy_Image * ) pyObjImage;
2224         image = py_img->image;
2225         ibuf = BKE_image_get_ibuf( image, NULL );
2226                 
2227         if( !ibuf )      /* if failed to load the image */
2228                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2229                                                                           "couldn't load image data in Blender" );
2230         if( !ibuf->rect )      /* no float yet */
2231                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2232                                                                           "Image has no byte rect" );
2233         
2234         /* Update the time tag of the image */
2235         tag_image_time(image);
2236
2237         /* set up a valid clipping rectangle.  if no clip rectangle was
2238          * given, this results in inclusion of the entire image.  otherwise,
2239          * the clipping is just checked against the bounds of the image.
2240          * if clipW or clipH are less than zero then they include as much of
2241          * the image as they can. */
2242         clipX = EXPP_ClampInt( clipX, 0, ibuf->x );
2243         clipY = EXPP_ClampInt( clipY, 0, ibuf->y );
2244         if( ( clipW < 0 ) || ( clipX+clipW > ibuf->x ) )
2245                 clipW = ibuf->x - clipX;
2246         if( ( clipH < 0 ) || ( clipY+clipH > ibuf->y ) )
2247                 clipH = ibuf->y - clipY;
2248
2249         /* -- we are "Go" to Draw! -- */
2250
2251         /* set the raster position.
2252          *
2253          * If the raster position is negative, then using glRasterPos2i() 
2254          * directly would cause it to be clipped.  Instead, we first establish 
2255          * a valid raster position within the clipping rectangle of the 
2256          * window and then use glBitmap() with a NULL image pointer to offset 
2257          * it to the true position we require.  To pick an initial valid 
2258          * raster position within the viewport, we query the clipping rectangle
2259          * and use its lower-left pixel.
2260          *
2261          * This particular technique is documented in the glRasterPos() man
2262          * page, although I haven't seen it used elsewhere in Blender.
2263          */
2264
2265         /* update (W): to fix a bug where images wouldn't get drawn if the bottom
2266          * left corner of the Scripts win were above a given height or to the right
2267          * of a given width, the code below is being commented out.  It should not
2268          * be needed anyway, because spaces in Blender are projected to lie inside
2269          * their areas, see src/drawscript.c for example.  Note: the
2270          * glaRasterPosSafe2i function in src/glutil.c does use the commented out
2271          * technique, but with 0,0 instead of scissorBox.  This function can be
2272          * a little optimized, based on glaDrawPixelsSafe in that same fine, but
2273          * we're too close to release 2.37 right now. */
2274         /*
2275         glGetFloatv( GL_SCISSOR_BOX, scissorBox );
2276         glRasterPos2i( scissorBox[0], scissorBox[1] );
2277         glBitmap( 0, 0, 0.0, 0.0, 
2278                 originX-scissorBox[0], originY-scissorBox[1], NULL );
2279         */
2280
2281         /* update (cont.): using these two lines instead:
2282          * (based on glaRasterPosSafe2i, but Ken Hughes deserves credit
2283          * for suggesting this exact fix in the bug tracker) */
2284         glRasterPos2i(0, 0);
2285         glBitmap( 0, 0, 0.0, 0.0, originX, originY, NULL );
2286
2287         /* set the zoom */
2288         glPixelZoom( zoomX, zoomY );
2289
2290         /* set the width of the image (ROW_LENGTH), and the offset to the
2291          * clip origin within the image in x (SKIP_PIXELS) and 
2292          * y (SKIP_ROWS) */
2293         glPixelStorei( GL_UNPACK_ROW_LENGTH,  ibuf->x );
2294         glPixelStorei( GL_UNPACK_SKIP_PIXELS, clipX );
2295         glPixelStorei( GL_UNPACK_SKIP_ROWS,   clipY );
2296
2297         /* draw the image */
2298         glDrawPixels( clipW, clipH, GL_RGBA, GL_UNSIGNED_BYTE, 
2299                 ibuf->rect );
2300
2301         /* restore the defaults for some parameters (we could also use a
2302          * glPushClientAttrib() and glPopClientAttrib() pair). */
2303         glPixelZoom( 1.0, 1.0 );
2304         glPixelStorei( GL_UNPACK_SKIP_ROWS,   0 );
2305         glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
2306         glPixelStorei( GL_UNPACK_ROW_LENGTH,  0 );
2307
2308         Py_RETURN_NONE;
2309
2310 }
2311
2312 PyObject *Draw_Init( void )
2313 {
2314         PyObject *submodule, *dict;
2315
2316         if( PyType_Ready( &Button_Type) < 0)
2317                 Py_RETURN_NONE;
2318
2319         submodule = Py_InitModule3( "Blender.Draw", Draw_methods, Draw_doc );
2320
2321         dict = PyModule_GetDict( submodule );
2322
2323 #define EXPP_ADDCONST(x) \
2324         EXPP_dict_set_item_str(dict, #x, PyInt_FromLong(x))
2325
2326         /* So, for example:
2327          * EXPP_ADDCONST(LEFTMOUSE) becomes
2328          * EXPP_dict_set_item_str(dict, "LEFTMOUSE", PyInt_FromLong(LEFTMOUSE)) 
2329          */
2330
2331         EXPP_ADDCONST( LEFTMOUSE );
2332         EXPP_ADDCONST( MIDDLEMOUSE );
2333         EXPP_ADDCONST( RIGHTMOUSE );
2334         EXPP_ADDCONST( WHEELUPMOUSE );
2335         EXPP_ADDCONST( WHEELDOWNMOUSE );
2336         EXPP_ADDCONST( MOUSEX );
2337         EXPP_ADDCONST( MOUSEY );
2338         EXPP_ADDCONST( TIMER0 );
2339         EXPP_ADDCONST( TIMER1 );
2340         EXPP_ADDCONST( TIMER2 );
2341         EXPP_ADDCONST( TIMER3 );
2342         EXPP_ADDCONST( KEYBD );
2343         EXPP_ADDCONST( RAWKEYBD );
2344         EXPP_ADDCONST( REDRAW );
2345         EXPP_ADDCONST( INPUTCHANGE );
2346         EXPP_ADDCONST( QFULL );
2347         EXPP_ADDCONST( WINFREEZE );
2348         EXPP_ADDCONST( WINTHAW );
2349         EXPP_ADDCONST( WINCLOSE );
2350         EXPP_ADDCONST( WINQUIT );
2351 #ifndef IRISGL
2352         EXPP_ADDCONST( Q_FIRSTTIME );
2353 #endif
2354         EXPP_ADDCONST( AKEY );
2355         EXPP_ADDCONST( BKEY );
2356         EXPP_ADDCONST( CKEY );
2357         EXPP_ADDCONST( DKEY );
2358         EXPP_ADDCONST( EKEY );
2359         EXPP_ADDCONST( FKEY );
2360         EXPP_ADDCONST( GKEY );
2361         EXPP_ADDCONST( HKEY );
2362         EXPP_ADDCONST( IKEY );
2363         EXPP_ADDCONST( JKEY );
2364         EXPP_ADDCONST( KKEY );
2365         EXPP_ADDCONST( LKEY );
2366         EXPP_ADDCONST( MKEY );
2367         EXPP_ADDCONST( NKEY );
2368         EXPP_ADDCONST( OKEY );
2369         EXPP_ADDCONST( PKEY );
2370         EXPP_ADDCONST( QKEY );
2371         EXPP_ADDCONST( RKEY );
2372         EXPP_ADDCONST( SKEY );
2373         EXPP_ADDCONST( TKEY );
2374         EXPP_ADDCONST( UKEY );
2375         EXPP_ADDCONST( VKEY );
2376         EXPP_ADDCONST( WKEY );
2377         EXPP_ADDCONST( XKEY );
2378         EXPP_ADDCONST( YKEY );
2379         EXPP_ADDCONST( ZKEY );
2380         EXPP_ADDCONST( ZEROKEY );
2381         EXPP_ADDCONST( ONEKEY );
2382         EXPP_ADDCONST( TWOKEY );
2383         EXPP_ADDCONST( THREEKEY );
2384         EXPP_ADDCONST( FOURKEY );
2385         EXPP_ADDCONST( FIVEKEY );
2386         EXPP_ADDCONST( SIXKEY );
2387         EXPP_ADDCONST( SEVENKEY );
2388         EXPP_ADDCONST( EIGHTKEY );
2389         EXPP_ADDCONST( NINEKEY );
2390         EXPP_ADDCONST( CAPSLOCKKEY );
2391         EXPP_ADDCONST( LEFTCTRLKEY );
2392         EXPP_ADDCONST( LEFTALTKEY );
2393         EXPP_ADDCONST( RIGHTALTKEY );
2394         EXPP_ADDCONST( RIGHTCTRLKEY );
2395         EXPP_ADDCONST( RIGHTSHIFTKEY );
2396         EXPP_ADDCONST( LEFTSHIFTKEY );
2397         EXPP_ADDCONST( ESCKEY );
2398         EXPP_ADDCONST( TABKEY );
2399         EXPP_ADDCONST( RETKEY );
2400         EXPP_ADDCONST( SPACEKEY );
2401         EXPP_ADDCONST( LINEFEEDKEY );
2402         EXPP_ADDCONST( BACKSPACEKEY );
2403         EXPP_ADDCONST( DELKEY );
2404         EXPP_ADDCONST( SEMICOLONKEY );
2405         EXPP_ADDCONST( PERIODKEY );
2406         EXPP_ADDCONST( COMMAKEY );
2407         EXPP_ADDCONST( QUOTEKEY );
2408         EXPP_ADDCONST( ACCENTGRAVEKEY );
2409         EXPP_ADDCONST( MINUSKEY );
2410         EXPP_ADDCONST( SLASHKEY );
2411         EXPP_ADDCONST( BACKSLASHKEY );
2412         EXPP_ADDCONST( EQUALKEY );
2413         EXPP_ADDCONST( LEFTBRACKETKEY );
2414         EXPP_ADDCONST( RIGHTBRACKETKEY );
2415         EXPP_ADDCONST( LEFTARROWKEY );
2416         EXPP_ADDCONST( DOWNARROWKEY );
2417         EXPP_ADDCONST( RIGHTARROWKEY );
2418         EXPP_ADDCONST( UPARROWKEY );
2419         EXPP_ADDCONST( PAD2 );
2420         EXPP_ADDCONST( PAD4 );
2421         EXPP_ADDCONST( PAD6 );
2422         EXPP_ADDCONST( PAD8 );
2423         EXPP_ADDCONST( PAD1 );
2424         EXPP_ADDCONST( PAD3 );
2425         EXPP_ADDCONST( PAD5 );
2426         EXPP_ADDCONST( PAD7 );
2427         EXPP_ADDCONST( PAD9 );
2428         EXPP_ADDCONST( PADPERIOD );
2429         EXPP_ADDCONST( PADSLASHKEY );
2430         EXPP_ADDCONST( PADASTERKEY );
2431         EXPP_ADDCONST( PAD0 );
2432         EXPP_ADDCONST( PADMINUS );
2433         EXPP_ADDCONST( PADENTER );
2434         EXPP_ADDCONST( PADPLUSKEY );
2435         EXPP_ADDCONST( F1KEY );
2436         EXPP_ADDCONST( F2KEY );
2437         EXPP_ADDCONST( F3KEY );
2438         EXPP_ADDCONST( F4KEY );
2439         EXPP_ADDCONST( F5KEY );
2440         EXPP_ADDCONST( F6KEY );
2441         EXPP_ADDCONST( F7KEY );
2442         EXPP_ADDCONST( F8KEY );
2443         EXPP_ADDCONST( F9KEY );
2444         EXPP_ADDCONST( F10KEY );
2445         EXPP_ADDCONST( F11KEY );
2446         EXPP_ADDCONST( F12KEY );
2447         EXPP_ADDCONST( PAUSEKEY );
2448         EXPP_ADDCONST( INSERTKEY );
2449         EXPP_ADDCONST( HOMEKEY );
2450         EXPP_ADDCONST( PAGEUPKEY );
2451         EXPP_ADDCONST( PAGEDOWNKEY );
2452         EXPP_ADDCONST( ENDKEY );
2453
2454         return submodule;
2455 }