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