UI: various changes
[blender-staging.git] / source / blender / editors / interface / interface.c
1 /**
2  * $Id: interface.c 16882 2008-10-02 12:29:45Z ton $
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  * Contributor(s): Blender Foundation 2002-2008, full recode.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <float.h>
29 #include <math.h>
30 #include <string.h>
31  
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_ID.h"
35 #include "DNA_listBase.h"
36 #include "DNA_screen_types.h"
37 #include "DNA_texture_types.h"
38 #include "DNA_userdef_types.h"
39
40 #include "BLI_arithb.h"
41 #include "BLI_blenlib.h"
42 #include "BLI_dynstr.h"
43
44 #include "BKE_context.h"
45 #include "BKE_idprop.h"
46 #include "BKE_library.h"
47 #include "BKE_screen.h"
48 #include "BKE_texture.h"
49 #include "BKE_utildefines.h"
50
51 #include "BIF_gl.h"
52 #include "BIF_glutil.h"
53
54 #include "UI_interface.h"
55 #include "UI_text.h"
56
57 #include "BMF_Api.h"
58 #ifdef INTERNATIONAL
59 #include "FTF_Api.h"
60 #endif
61
62 #include "ED_screen.h"
63
64 #include "WM_api.h"
65 #include "WM_types.h"
66 #include "wm_subwindow.h"
67 #include "wm_window.h"
68
69 #include "RNA_access.h"
70 #include "RNA_types.h"
71
72 #include "interface_intern.h"
73
74 #define MENU_WIDTH                      120
75 #define MENU_ITEM_HEIGHT        20
76 #define MENU_SEP_HEIGHT         6
77
78 /* 
79  * a full doc with API notes can be found in bf-blender/blender/doc/interface_API.txt
80  * 
81  * uiBlahBlah()         external function
82  * ui_blah_blah()       internal function
83  */
84
85 static void ui_free_but(const bContext *C, uiBut *but);
86
87 /* ************ GLOBALS ************* */
88
89 static uiFont UIfont[UI_ARRAY];  // no init needed
90
91 /* ************* translation ************** */
92
93 int ui_translate_buttons()
94 {
95         return (U.transopts & USER_TR_BUTTONS);
96 }
97
98 int ui_translate_menus()
99 {
100         return (U.transopts & USER_TR_MENUS);
101 }
102
103 int ui_translate_tooltips()
104 {
105         return (U.transopts & USER_TR_TOOLTIPS);
106 }
107
108 /* ************* window matrix ************** */
109
110 void ui_block_to_window_fl(const ARegion *ar, uiBlock *block, float *x, float *y)
111 {
112         float gx, gy;
113         int sx, sy, getsizex, getsizey;
114
115         getsizex= ar->winrct.xmax-ar->winrct.xmin+1;
116         getsizey= ar->winrct.ymax-ar->winrct.ymin+1;
117         sx= ar->winrct.xmin;
118         sy= ar->winrct.ymin;
119
120         gx= *x;
121         gy= *y;
122
123         if(block->panel) {
124                 gx += block->panel->ofsx;
125                 gy += block->panel->ofsy;
126         }
127
128         *x= ((float)sx) + ((float)getsizex)*(0.5+ 0.5*(gx*block->winmat[0][0]+ gy*block->winmat[1][0]+ block->winmat[3][0]));
129         *y= ((float)sy) + ((float)getsizey)*(0.5+ 0.5*(gx*block->winmat[0][1]+ gy*block->winmat[1][1]+ block->winmat[3][1]));
130 }
131
132 void ui_block_to_window(const ARegion *ar, uiBlock *block, int *x, int *y)
133 {
134         float fx, fy;
135
136         fx= *x;
137         fy= *y;
138
139         ui_block_to_window_fl(ar, block, &fx, &fy);
140
141         *x= (int)(fx+0.5f);
142         *y= (int)(fy+0.5f);
143 }
144
145 void ui_block_to_window_rct(const ARegion *ar, uiBlock *block, rctf *graph, rcti *winr)
146 {
147         rctf tmpr;
148
149         tmpr= *graph;
150         ui_block_to_window_fl(ar, block, &tmpr.xmin, &tmpr.ymin);
151         ui_block_to_window_fl(ar, block, &tmpr.xmax, &tmpr.ymax);
152
153         winr->xmin= tmpr.xmin;
154         winr->ymin= tmpr.ymin;
155         winr->xmax= tmpr.xmax;
156         winr->ymax= tmpr.ymax;
157 }
158
159 void ui_window_to_block_fl(const ARegion *ar, uiBlock *block, float *x, float *y)       /* for mouse cursor */
160 {
161         float a, b, c, d, e, f, px, py;
162         int sx, sy, getsizex, getsizey;
163
164         getsizex= ar->winrct.xmax-ar->winrct.xmin+1;
165         getsizey= ar->winrct.ymax-ar->winrct.ymin+1;
166         sx= ar->winrct.xmin;
167         sy= ar->winrct.ymin;
168
169         a= .5*((float)getsizex)*block->winmat[0][0];
170         b= .5*((float)getsizex)*block->winmat[1][0];
171         c= .5*((float)getsizex)*(1.0+block->winmat[3][0]);
172
173         d= .5*((float)getsizey)*block->winmat[0][1];
174         e= .5*((float)getsizey)*block->winmat[1][1];
175         f= .5*((float)getsizey)*(1.0+block->winmat[3][1]);
176
177         px= *x - sx;
178         py= *y - sy;
179
180         *y=  (a*(py-f) + d*(c-px))/(a*e-d*b);
181         *x= (px- b*(*y)- c)/a;
182
183         if(block->panel) {
184                 *x -= block->panel->ofsx;
185                 *y -= block->panel->ofsy;
186         }
187 }
188
189 void ui_window_to_block(const ARegion *ar, uiBlock *block, int *x, int *y)
190 {
191         float fx, fy;
192
193         fx= *x;
194         fy= *y;
195
196         ui_window_to_block_fl(ar, block, &fx, &fy);
197
198         *x= (int)(fx+0.5f);
199         *y= (int)(fy+0.5f);
200 }
201
202 void ui_window_to_region(const ARegion *ar, int *x, int *y)
203 {
204         *x-= ar->winrct.xmin;
205         *y-= ar->winrct.ymin;
206 }
207
208 /* ******************* block calc ************************* */
209
210 /* only for pulldowns */
211 void uiTextBoundsBlock(uiBlock *block, int addval)
212 {
213         uiBut *bt;
214         int i = 0, j, x1addval= 0, nextcol;
215         
216         bt= block->buttons.first;
217         while(bt) {
218                 if(bt->type!=SEPR) {
219                         int transopts= ui_translate_buttons();
220                         if(bt->type==TEX || bt->type==IDPOIN) transopts= 0;
221                         j= UI_GetStringWidth(bt->font, bt->drawstr, transopts);
222
223                         if(j > i) i = j;
224                 }
225                 bt= bt->next;
226         }
227
228         /* cope with multi collumns */
229         bt= block->buttons.first;
230         while(bt) {
231                 if(bt->next && bt->x1 < bt->next->x1)
232                         nextcol= 1;
233                 else nextcol= 0;
234                 
235                 bt->x1 = x1addval;
236                 bt->x2 = bt->x1 + i + addval;
237                 
238                 ui_check_but(bt);       // clips text again
239                 
240                 if(nextcol)
241                         x1addval+= i + addval;
242                 
243                 bt= bt->next;
244         }
245 }
246
247 void uiBoundsBlock(uiBlock *block, int addval)
248 {
249         uiBut *bt;
250         int xof;
251         
252         if(block==NULL)
253                 return;
254         
255         if(block->buttons.first==NULL) {
256                 if(block->panel) {
257                         block->minx= 0.0; block->maxx= block->panel->sizex;
258                         block->miny= 0.0; block->maxy= block->panel->sizey;
259                 }
260         }
261         else {
262         
263                 block->minx= block->miny= 10000;
264                 block->maxx= block->maxy= -10000;
265                 
266                 bt= block->buttons.first;
267                 while(bt) {
268                         if(bt->x1 < block->minx) block->minx= bt->x1;
269                         if(bt->y1 < block->miny) block->miny= bt->y1;
270         
271                         if(bt->x2 > block->maxx) block->maxx= bt->x2;
272                         if(bt->y2 > block->maxy) block->maxy= bt->y2;
273                         
274                         bt= bt->next;
275                 }
276                 
277                 block->minx -= addval;
278                 block->miny -= addval;
279                 block->maxx += addval;
280                 block->maxy += addval;
281         }
282
283         /* hardcoded exception... but that one is annoying with larger safety */ 
284         bt= block->buttons.first;
285         if(bt && strncmp(bt->str, "ERROR", 5)==0) xof= 10;
286         else xof= 40;
287         
288         block->safety.xmin= block->minx-xof;
289         block->safety.ymin= block->miny-xof;
290         block->safety.xmax= block->maxx+xof;
291         block->safety.ymax= block->maxy+xof;
292 }
293
294 void uiBlockTranslate(uiBlock *block, int x, int y)
295 {
296         uiBut *bt;
297
298         for(bt= block->buttons.first; bt; bt=bt->next) {
299                 bt->x1 += x;
300                 bt->y1 += y;
301                 bt->x2 += x;
302                 bt->y2 += y;
303         }
304
305         block->minx += x;
306         block->miny += y;
307         block->maxx += x;
308         block->maxy += y;
309 }
310
311 void uiBlockOrigin(uiBlock *block)
312 {
313         uiBut *bt;
314         int minx= 10000, miny= 10000;
315
316         for(bt= block->buttons.first; bt; bt=bt->next) {
317                 if(bt->x1 < minx) minx= bt->x1;
318                 if(bt->y1 < miny) miny= bt->y1;
319         }
320
321         uiBlockTranslate(block, -minx, -miny);
322 }
323
324 void ui_autofill(uiBlock *block)
325 {
326         uiBut *but;
327         float *maxw, *maxh, startx = 0, starty, height = 0;
328         float totmaxh;
329         int rows=0, /*  cols=0, */ i, lasti;
330         
331         /* first count rows */
332         but= block->buttons.last;
333         rows= but->x1+1;
334
335         /* calculate max width / height for each row */
336         maxw= MEM_callocN(sizeof(float)*rows, "maxw");
337         maxh= MEM_callocN(sizeof(float)*rows, "maxh");
338         but= block->buttons.first;
339         while(but) {
340                 i= but->x1;
341                 if( maxh[i] < but->y2) maxh[i]= but->y2;
342                 maxw[i] += but->x2;
343                 but= but->next;
344         }
345         
346         totmaxh= 0.0;
347         for(i=0; i<rows; i++) totmaxh+= maxh[i];
348         
349         /* apply widths/heights */
350         starty= block->maxy;
351         but= block->buttons.first;
352         lasti= -1;
353         while(but) {
354                 // signal for aligning code
355                 but->flag |= UI_BUT_ALIGN_DOWN;
356                 
357                 i= but->x1;
358
359                 if(i!=lasti) {
360                         startx= block->minx;
361                         height= (maxh[i]*(block->maxy-block->miny))/totmaxh;
362                         starty-= height;
363                         lasti= i;
364                 }
365                 
366                 but->y1= starty+but->aspect;
367                 but->y2= but->y1+height-but->aspect;
368                 
369                 but->x2= (but->x2*(block->maxx-block->minx))/maxw[i];
370                 but->x1= startx+but->aspect;
371                 
372                 startx+= but->x2;
373                 but->x2+= but->x1-but->aspect;
374                 
375                 ui_check_but(but);
376                 
377                 but= but->next;
378         }
379         
380         uiBlockEndAlign(block);
381         
382         MEM_freeN(maxw); MEM_freeN(maxh);       
383         block->autofill= 0;
384 }
385
386 /* ************** LINK LINE DRAWING  ************* */
387
388 /* link line drawing is not part of buttons or theme.. so we stick with it here */
389
390 static void ui_draw_linkline(uiBut *but, uiLinkLine *line)
391 {
392         float vec1[2], vec2[2];
393
394         if(line->from==NULL || line->to==NULL) return;
395         
396         vec1[0]= (line->from->x1+line->from->x2)/2.0;
397         vec1[1]= (line->from->y1+line->from->y2)/2.0;
398         vec2[0]= (line->to->x1+line->to->x2)/2.0;
399         vec2[1]= (line->to->y1+line->to->y2)/2.0;
400         
401         if(line->flag & UI_SELECT) UI_ThemeColorShade(but->themecol, 80);
402         else glColor3ub(0,0,0);
403         fdrawline(vec1[0], vec1[1], vec2[0], vec2[1]);
404 }
405
406 static void ui_draw_links(uiBlock *block)
407 {
408         uiBut *but;
409         uiLinkLine *line;
410         
411         but= block->buttons.first;
412         while(but) {
413                 if(but->type==LINK && but->link) {
414                         line= but->link->lines.first;
415                         while(line) {
416                                 ui_draw_linkline(but, line);
417                                 line= line->next;
418                         }
419                 }
420                 but= but->next;
421         }       
422 }
423
424 /* ************** BLOCK ENDING FUNCTION ************* */
425
426 static int ui_but_equals_old(uiBut *but, uiBut *oldbut)
427 {
428         /* various properties are being compared here, hopfully sufficient
429          * to catch all cases, but it is simple to add more checks later */
430         if(but->retval != oldbut->retval) return 0;
431         if(but->poin != oldbut->poin || but->pointype != oldbut->pointype) return 0;
432         if(but->rnapoin.data != oldbut->rnapoin.data) return 0;
433         if(but->rnaprop != oldbut->rnaprop)
434         if(but->rnaindex != oldbut->rnaindex) return 0;
435         if(but->func != oldbut->func) return 0;
436         if(but->func_arg1 != oldbut->func_arg1) return 0;
437         if(but->func_arg2 != oldbut->func_arg2) return 0;
438
439         return 1;
440 }
441
442 static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut *but)
443 {
444         uiBlock *oldblock;
445         uiBut *oldbut;
446         int found= 0;
447
448         oldblock= block->oldblock;
449         if(!oldblock)
450                 return found;
451
452         for(oldbut=oldblock->buttons.first; oldbut; oldbut=oldbut->next) {
453                 if(ui_but_equals_old(oldbut, but)) {
454                         if(oldbut->active) {
455                                 but->flag= oldbut->flag;
456                                 but->active= oldbut->active;
457                                 but->pos= oldbut->pos;
458                                 but->editstr= oldbut->editstr;
459                                 but->editval= oldbut->editval;
460                                 but->editvec= oldbut->editvec;
461                                 but->editcoba= oldbut->editcoba;
462                                 but->editcumap= oldbut->editcumap;
463                                 but->selsta= oldbut->selsta;
464                                 but->selend= oldbut->selend;
465                                 found= 1;
466
467                                 oldbut->active= NULL;
468                         }
469
470                         /* ensures one button can get activated, and in case the buttons
471                          * draw are the same this gives O(1) lookup for each button */
472                         BLI_remlink(&oldblock->buttons, oldbut);
473                         ui_free_but(C, oldbut);
474                         
475                         break;
476                 }
477         }
478         
479         return found;
480 }
481
482 static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
483 {
484         uiBut *but;
485         char buf[512], *butstr;
486
487         /* XXX bounds? */
488         for(but=block->buttons.first; but; but=but->next) {
489                 if(but->opname) {
490                         if(WM_key_event_operator_string(C, but->opname, but->opcontext, buf, sizeof(buf))) {
491                                 butstr= MEM_mallocN(strlen(but->str)+strlen(buf)+2, "menu_block_set_keymaps");
492                                 strcpy(butstr, but->str);
493                                 strcat(butstr, "|");
494                                 strcat(butstr, buf);
495
496                                 but->str= but->strdata;
497                                 BLI_strncpy(but->str, butstr, sizeof(but->strdata));
498                                 MEM_freeN(butstr);
499
500                                 ui_check_but(but);
501                         }
502                 }
503         }
504 }
505
506 void uiEndBlock(const bContext *C, uiBlock *block)
507 {
508         uiBut *but;
509
510         /* inherit flags from 'old' buttons that was drawn here previous, based
511          * on matching buttons, we need this to make button event handling non
512          * blocking, while still alowing buttons to be remade each redraw as it
513          * is expected by blender code */
514         for(but=block->buttons.first; but; but=but->next)
515                 if(ui_but_update_from_old_block(C, block, but))
516                         ui_check_but(but);
517
518         if(block->oldblock) {
519                 block->auto_open= block->oldblock->auto_open;
520                 block->auto_open_last= block->oldblock->auto_open_last;
521                 block->tooltipdisabled= block->oldblock->tooltipdisabled;
522
523                 block->oldblock= NULL;
524         }
525
526         /* handle pending stuff */
527         if(block->flag & UI_BLOCK_LOOP) ui_menu_block_set_keymaps(C, block);
528         if(block->autofill) ui_autofill(block);
529         if(block->minx==0.0 && block->maxx==0.0) uiBoundsBlock(block, 0);
530         if(block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block);
531 }
532
533 /* ************** BLOCK DRAWING FUNCTION ************* */
534
535 void uiDrawBlock(const bContext *C, uiBlock *block)
536 {
537         uiBut *but;
538
539         /* we set this only once */
540         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
541         
542         if(block->flag & UI_BLOCK_LOOP)
543                 uiDrawMenuBox(block->minx, block->miny, block->maxx, block->maxy, block->flag, block->direction);
544         else if(block->panel)
545                 ui_draw_panel(CTX_wm_region(C), block);
546
547         if(block->drawextra) block->drawextra(C, block);
548
549         for (but= block->buttons.first; but; but= but->next)
550                 ui_draw_but(but);
551
552         ui_draw_links(block);
553 }
554
555 /* ************* EVENTS ************* */
556
557 static void ui_is_but_sel(uiBut *but)
558 {
559         double value;
560         int lvalue;
561         short push=0, true=1;
562
563         value= ui_get_but_val(but);
564
565         if( but->type==TOGN  || but->type==ICONTOGN) true= 0;
566
567         if( but->bit ) {
568                 lvalue= (int)value;
569                 if( BTST(lvalue, (but->bitnr)) ) push= true;
570                 else push= !true;
571         }
572         else {
573                 switch(but->type) {
574                 case BUT:
575                         push= 2;
576                         break;
577                 case KEYEVT:
578                         if (value==-1) push= 1;
579                         break;
580                 case TOG:
581                 case TOGR:
582                 case TOG3:
583                 case BUT_TOGDUAL:
584                 case ICONTOG:
585                         if(value!=but->min) push= 1;
586                         break;
587                 case ICONTOGN:
588                 case TOGN:
589                         if(value==0.0) push= 1;
590                         break;
591                 case ROW:
592                         if(value == but->max) push= 1;
593                         break;
594                 case COL:
595                         push= 1;
596                         break;
597                 default:
598                         push= 2;
599                         break;
600                 }
601         }
602         
603         if(push==2);
604         else if(push==1) but->flag |= UI_SELECT;
605         else but->flag &= ~UI_SELECT;
606 }
607
608 /* XXX 2.50 no links supported yet */
609
610 #if 0
611 static uiBut *ui_get_valid_link_button(uiBlock *block, uiBut *but, short *mval)
612 {
613         uiBut *bt;
614         
615                 /* find button to link to */
616         for (bt= block->buttons.first; bt; bt= bt->next)
617                 if(bt!=but && uibut_contains_pt(bt, mval))
618                         break;
619
620         if (bt) {
621                 if (but->type==LINK && bt->type==INLINK) {
622                         if( but->link->tocode == (int)bt->min ) {
623                                 return bt;
624                         }
625                 }
626                 else if(but->type==INLINK && bt->type==LINK) {
627                         if( bt->link->tocode == (int)but->min ) {
628                                 return bt;
629                         }
630                 }
631         }
632
633         return NULL;
634 }
635
636 static int ui_is_a_link(uiBut *from, uiBut *to)
637 {
638         uiLinkLine *line;
639         uiLink *link;
640         
641         link= from->link;
642         if(link) {
643                 line= link->lines.first;
644                 while(line) {
645                         if(line->from==from && line->to==to) return 1;
646                         line= line->next;
647                 }
648         }
649         return 0;
650 }
651
652 static uiBut *ui_find_inlink(uiBlock *block, void *poin)
653 {
654         uiBut *but;
655         
656         but= block->buttons.first;
657         while(but) {
658                 if(but->type==INLINK) {
659                         if(but->poin == poin) return but;
660                 }
661                 but= but->next;
662         }
663         return NULL;
664 }
665
666 static void ui_add_link_line(ListBase *listb, uiBut *but, uiBut *bt)
667 {
668         uiLinkLine *line;
669         
670         line= MEM_callocN(sizeof(uiLinkLine), "linkline");
671         BLI_addtail(listb, line);
672         line->from= but;
673         line->to= bt;
674 }
675
676 uiBut *uiFindInlink(uiBlock *block, void *poin)
677 {
678         return ui_find_inlink(block, poin);
679 }
680
681 void uiComposeLinks(uiBlock *block)
682 {
683         uiBut *but, *bt;
684         uiLink *link;
685         void ***ppoin;
686         int a;
687         
688         but= block->buttons.first;
689         while(but) {
690                 if(but->type==LINK) {
691                         link= but->link;
692                         
693                         /* for all pointers in the array */
694                         if(link) {
695                                 if(link->ppoin) {
696                                         ppoin= link->ppoin;
697                                         for(a=0; a < *(link->totlink); a++) {
698                                                 bt= ui_find_inlink(block, (*ppoin)[a] );
699                                                 if(bt) {
700                                                         ui_add_link_line(&link->lines, but, bt);
701                                                 }
702                                         }
703                                 }
704                                 else if(link->poin) {
705                                         bt= ui_find_inlink(block, *(link->poin) );
706                                         if(bt) {
707                                                 ui_add_link_line(&link->lines, but, bt);
708                                         }
709                                 }
710                         }
711                 }
712                 but= but->next;
713         }
714 }
715
716 static void ui_add_link(uiBut *from, uiBut *to)
717 {
718         /* in 'from' we have to add a link to 'to' */
719         uiLink *link;
720         void **oldppoin;
721         int a;
722         
723         if(ui_is_a_link(from, to)) {
724                 printf("already exists\n");
725                 return;
726         }
727         
728         link= from->link;
729
730         /* are there more pointers allowed? */
731         if(link->ppoin) {
732                 oldppoin= *(link->ppoin);
733                 
734                 (*(link->totlink))++;
735                 *(link->ppoin)= MEM_callocN( *(link->totlink)*sizeof(void *), "new link");
736
737                 for(a=0; a< (*(link->totlink))-1; a++) {
738                         (*(link->ppoin))[a]= oldppoin[a];
739                 }
740                 (*(link->ppoin))[a]= to->poin;
741                 
742                 if(oldppoin) MEM_freeN(oldppoin);
743         }
744         else {
745                 *(link->poin)= to->poin;
746         }
747         
748 }
749
750 static int ui_do_but_LINK(uiBlock *block, uiBut *but)
751 {
752         /* 
753          * This button only visualizes, the dobutton mode
754          * can add a new link, but then the whole system
755          * should be redrawn/initialized. 
756          * 
757          */
758         uiBut *bt=0, *bto=NULL;
759         short sval[2], mval[2], mvalo[2], first= 1;
760
761         uiGetMouse(curarea->win, sval);
762         mvalo[0]= sval[0];
763         mvalo[1]= sval[1];
764         
765         while (get_mbut() & L_MOUSE) {
766                 uiGetMouse(curarea->win, mval);
767
768                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || first) {                   
769                                 /* clear completely, because of drawbuttons */
770                         bt= ui_get_valid_link_button(block, but, mval);
771                         if(bt) {
772                                 bt->flag |= UI_ACTIVE;
773                                 ui_draw_but(bt);
774                         }
775                         if(bto && bto!=bt) {
776                                 bto->flag &= ~UI_ACTIVE;
777                                 ui_draw_but(bto);
778                         }
779                         bto= bt;
780
781                         if (!first) {
782                                 glutil_draw_front_xor_line(sval[0], sval[1], mvalo[0], mvalo[1]);
783                         }
784                         glutil_draw_front_xor_line(sval[0], sval[1], mval[0], mval[1]);
785
786                         mvalo[0]= mval[0];
787                         mvalo[1]= mval[1];
788
789                         first= 0;
790                 }
791                 else UI_wait_for_statechange();         
792         }
793         
794         if (!first) {
795                 glutil_draw_front_xor_line(sval[0], sval[1], mvalo[0], mvalo[1]);
796         }
797
798         if(bt) {
799                 if(but->type==LINK) ui_add_link(but, bt);
800                 else ui_add_link(bt, but);
801
802                 scrarea_queue_winredraw(curarea);
803         }
804
805         return 0;
806 }
807 #endif
808
809 /* ************************************************ */
810
811 void uiBlockSetButLock(uiBlock *block, int val, char *lockstr)
812 {
813         block->lock |= val;
814         if(val) block->lockstr= lockstr;
815 }
816
817 void uiBlockClearButLock(uiBlock *block)
818 {
819         block->lock= 0;
820         block->lockstr= NULL;
821 }
822
823 /* *************************************************************** */
824
825 /* XXX 2.50 no button editing */
826
827 #if 0
828 static void setup_file(uiBlock *block)
829 {
830         uiBut *but;
831         FILE *fp;
832
833         fp= fopen("butsetup","w");
834         if(fp==NULL);
835         else {
836                 but= block->buttons.first;
837                 while(but) {
838                         ui_check_but(but);
839                         fprintf(fp,"%d,%d,%d,%d   %s %s\n", (int)but->x1, (int)but->y1, (int)( but->x2-but->x1), (int)(but->y2-but->y1), but->str, but->tip);
840                         but= but->next;
841                 }
842                 fclose(fp);
843         }
844 }
845
846
847 static void edit_but(uiBlock *block, uiBut *but, uiEvent *uevent)
848 {
849         short dx, dy, mval[2], mvalo[2], didit=0;
850         
851         getmouseco_sc(mvalo);
852         while(TRUE) {
853                 if( !(get_mbut() & L_MOUSE) ) break;    
854         
855                 getmouseco_sc(mval);
856                 dx= (mval[0]-mvalo[0]);
857                 dy= (mval[1]-mvalo[1]);
858                 
859                 if(dx!=0 || dy!=0) {
860                         mvalo[0]= mval[0];
861                         mvalo[1]= mval[1];
862                         
863                         cpack(0xc0c0c0);
864                         glRectf(but->x1-2, but->y1-2, but->x2+2, but->y2+2); 
865                         
866                         if((uevent->qual & LR_SHIFTKEY)==0) {
867                                 but->x1 += dx;
868                                 but->y1 += dy;
869                         }
870                         but->x2 += dx;
871                         but->y2 += dy;
872                         
873                         ui_draw_but(but);
874                         ui_block_flush_back(but->block);
875                         didit= 1;
876
877                 }
878                 /* idle for this poor code */
879                 else PIL_sleep_ms(30);
880         }
881         if(didit) setup_file(block);
882 }
883 #endif
884
885 /* XXX 2.50 no links supported yet */
886 #if 0
887 static void ui_delete_active_linkline(uiBlock *block)
888 {
889         uiBut *but;
890         uiLink *link;
891         uiLinkLine *line, *nline;
892         int a, b;
893         
894         but= block->buttons.first;
895         while(but) {
896                 if(but->type==LINK && but->link) {
897                         line= but->link->lines.first;
898                         while(line) {
899                                 
900                                 nline= line->next;
901                                 
902                                 if(line->flag & UI_SELECT) {
903                                         BLI_remlink(&but->link->lines, line);
904
905                                         link= line->from->link;
906
907                                         /* are there more pointers allowed? */
908                                         if(link->ppoin) {
909                                                 
910                                                 if(*(link->totlink)==1) {
911                                                         *(link->totlink)= 0;
912                                                         MEM_freeN(*(link->ppoin));
913                                                         *(link->ppoin)= NULL;
914                                                 }
915                                                 else {
916                                                         b= 0;
917                                                         for(a=0; a< (*(link->totlink)); a++) {
918                                                                 
919                                                                 if( (*(link->ppoin))[a] != line->to->poin ) {
920                                                                         (*(link->ppoin))[b]= (*(link->ppoin))[a];
921                                                                         b++;
922                                                                 }
923                                                         }       
924                                                         (*(link->totlink))--;
925                                                 }
926                                         }
927                                         else {
928                                                 *(link->poin)= NULL;
929                                         }
930
931                                         MEM_freeN(line);
932                                 }
933                                 line= nline;
934                         }
935                 }
936                 but= but->next;
937         }
938         
939         /* temporal! these buttons can be everywhere... */
940         allqueue(REDRAWBUTSLOGIC, 0);
941 }
942
943 static void ui_do_active_linklines(uiBlock *block, short *mval)
944 {
945         uiBut *but;
946         uiLinkLine *line, *act= NULL;
947         float mindist= 12.0, fac, v1[2], v2[2], v3[3];
948         int foundone= 0; 
949         
950         if(mval) {
951                 v1[0]= mval[0];
952                 v1[1]= mval[1];
953                 
954                 /* find a line close to the mouse */
955                 but= block->buttons.first;
956                 while(but) {
957                         if(but->type==LINK && but->link) {
958                                 foundone= 1;
959                                 line= but->link->lines.first;
960                                 while(line) {
961                                         v2[0]= line->from->x2;
962                                         v2[1]= (line->from->y1+line->from->y2)/2.0;
963                                         v3[0]= line->to->x1;
964                                         v3[1]= (line->to->y1+line->to->y2)/2.0;
965                                         
966                                         fac= PdistVL2Dfl(v1, v2, v3);
967                                         if(fac < mindist) {
968                                                 mindist= fac;
969                                                 act= line;
970                                         }
971                                         line= line->next;
972                                 }
973                         }
974                         but= but->next;
975                 }
976         }
977
978         /* check for a 'found one' to prevent going to 'frontbuffer' mode.
979                 this slows done gfx quite some, and at OSX the 'finish' forces a swapbuffer */
980         if(foundone) {
981                 glDrawBuffer(GL_FRONT);
982                 
983                 /* draw */
984                 but= block->buttons.first;
985                 while(but) {
986                         if(but->type==LINK && but->link) {
987                                 line= but->link->lines.first;
988                                 while(line) {
989                                         if(line==act) {
990                                                 if((line->flag & UI_SELECT)==0) {
991                                                         line->flag |= UI_SELECT;
992                                                         ui_draw_linkline(but, line);
993                                                 }
994                                         }
995                                         else if(line->flag & UI_SELECT) {
996                                                 line->flag &= ~UI_SELECT;
997                                                 ui_draw_linkline(but, line);
998                                         }
999                                         line= line->next;
1000                                 }
1001                         }
1002                         but= but->next;
1003                 }
1004                 bglFlush();
1005                 glDrawBuffer(GL_BACK);
1006         }
1007 }
1008 #endif
1009
1010 /* ******************************************************* */
1011
1012 /* XXX 2.50 no screendump supported yet */
1013
1014 #if 0
1015 /* nasty but safe way to store screendump rect */
1016 static int scr_x=0, scr_y=0, scr_sizex=0, scr_sizey=0;
1017
1018 static void ui_set_screendump_bbox(uiBlock *block)
1019 {
1020         if(block) {
1021                 scr_x= block->minx;
1022                 scr_y= block->miny;
1023                 scr_sizex= block->maxx - block->minx;
1024                 scr_sizey= block->maxy - block->miny;
1025         }
1026         else {
1027                 scr_sizex= scr_sizey= 0;
1028         }
1029 }
1030
1031 /* used for making screenshots for menus, called in screendump.c */
1032 int uiIsMenu(int *x, int *y, int *sizex, int *sizey)
1033 {
1034         if(scr_sizex!=0 && scr_sizey!=0) {
1035                 *x= scr_x;
1036                 *y= scr_y;
1037                 *sizex= scr_sizex;
1038                 *sizey= scr_sizey;
1039                 return 1;
1040         }
1041         
1042         return 0;
1043 }
1044 #endif
1045
1046 /* *********************** data get/set ***********************
1047  * this either works with the pointed to data, or can work with
1048  * an edit override pointer while dragging for example */
1049
1050 /* for buttons pointing to color for example */
1051 void ui_get_but_vectorf(uiBut *but, float *vec)
1052 {
1053         PropertyRNA *prop;
1054         int a, tot;
1055
1056         if(but->editvec) {
1057                 VECCOPY(vec, but->editvec);
1058                 return;
1059         }
1060
1061         if(but->rnaprop) {
1062                 prop= but->rnaprop;
1063
1064                 vec[0]= vec[1]= vec[2]= 0.0f;
1065
1066                 if(RNA_property_type(&but->rnapoin, prop) == PROP_FLOAT) {
1067                         tot= RNA_property_array_length(&but->rnapoin, prop);
1068                         tot= MIN2(tot, 3);
1069
1070                         for(a=0; a<tot; a++)
1071                                 vec[a]= RNA_property_float_get_array(&but->rnapoin, prop, a);
1072                 }
1073         }
1074         else if(but->pointype == CHA) {
1075                 char *cp= (char *)but->poin;
1076                 vec[0]= ((float)cp[0])/255.0;
1077                 vec[1]= ((float)cp[1])/255.0;
1078                 vec[2]= ((float)cp[2])/255.0;
1079         }
1080         else if(but->pointype == FLO) {
1081                 float *fp= (float *)but->poin;
1082                 VECCOPY(vec, fp);
1083         }
1084 }
1085
1086 /* for buttons pointing to color for example */
1087 void ui_set_but_vectorf(uiBut *but, float *vec)
1088 {
1089         PropertyRNA *prop;
1090         int a, tot;
1091
1092         if(but->editvec) {
1093                 VECCOPY(but->editvec, vec);
1094                 return;
1095         }
1096
1097         if(but->rnaprop) {
1098                 prop= but->rnaprop;
1099
1100                 if(RNA_property_type(&but->rnapoin, prop) == PROP_FLOAT) {
1101                         tot= RNA_property_array_length(&but->rnapoin, prop);
1102                         tot= MIN2(tot, 3);
1103
1104                         for(a=0; a<tot; a++)
1105                                 RNA_property_float_set_array(&but->rnapoin, prop, a, vec[a]);
1106                 }
1107         }
1108         else if(but->pointype == CHA) {
1109                 char *cp= (char *)but->poin;
1110                 cp[0]= (char)(0.5 +vec[0]*255.0);
1111                 cp[1]= (char)(0.5 +vec[1]*255.0);
1112                 cp[2]= (char)(0.5 +vec[2]*255.0);
1113         }
1114         else if(but->pointype == FLO) {
1115                 float *fp= (float *)but->poin;
1116                 VECCOPY(fp, vec);
1117         }
1118 }
1119
1120 int ui_is_but_float(uiBut *but)
1121 {
1122         if(but->pointype==FLO && but->poin)
1123                 return 1;
1124         
1125         if(but->rnaprop && RNA_property_type(&but->rnapoin, but->rnaprop) == PROP_FLOAT)
1126                 return 1;
1127         
1128         return 0;
1129 }
1130
1131 double ui_get_but_val(uiBut *but)
1132 {
1133         PropertyRNA *prop;
1134         double value = 0.0;
1135
1136         if(but->editval) { return *(but->editval); }
1137         if(but->poin==NULL && but->rnapoin.data==NULL) return 0.0;
1138
1139         if(but->rnaprop) {
1140                 prop= but->rnaprop;
1141
1142                 switch(RNA_property_type(&but->rnapoin, prop)) {
1143                         case PROP_BOOLEAN:
1144                                 if(RNA_property_array_length(&but->rnapoin, prop))
1145                                         value= RNA_property_boolean_get_array(&but->rnapoin, prop, but->rnaindex);
1146                                 else
1147                                         value= RNA_property_boolean_get(&but->rnapoin, prop);
1148                                 break;
1149                         case PROP_INT:
1150                                 if(RNA_property_array_length(&but->rnapoin, prop))
1151                                         value= RNA_property_int_get_array(&but->rnapoin, prop, but->rnaindex);
1152                                 else
1153                                         value= RNA_property_int_get(&but->rnapoin, prop);
1154                                 break;
1155                         case PROP_FLOAT:
1156                                 if(RNA_property_array_length(&but->rnapoin, prop))
1157                                         value= RNA_property_float_get_array(&but->rnapoin, prop, but->rnaindex);
1158                                 else
1159                                         value= RNA_property_float_get(&but->rnapoin, prop);
1160                                 break;
1161                         case PROP_ENUM:
1162                                 value= RNA_property_enum_get(&but->rnapoin, prop);
1163                                 break;
1164                         default:
1165                                 value= 0.0;
1166                                 break;
1167                 }
1168         }
1169         else if(but->type== HSVSLI) {
1170                 float h, s, v, *fp;
1171                 
1172                 fp= (but->editvec)? but->editvec: (float *)but->poin;
1173                 rgb_to_hsv(fp[0], fp[1], fp[2], &h, &s, &v);
1174
1175                 switch(but->str[0]) {
1176                         case 'H': value= h; break;
1177                         case 'S': value= s; break;
1178                         case 'V': value= v; break;
1179                 }
1180         } 
1181         else if( but->pointype == CHA ) {
1182                 value= *(char *)but->poin;
1183         }
1184         else if( but->pointype == SHO ) {
1185                 value= *(short *)but->poin;
1186         } 
1187         else if( but->pointype == INT ) {
1188                 value= *(int *)but->poin;
1189         } 
1190         else if( but->pointype == FLO ) {
1191                 value= *(float *)but->poin;
1192         }
1193     
1194         return value;
1195 }
1196
1197 void ui_set_but_val(uiBut *but, double value)
1198 {
1199         PropertyRNA *prop;
1200
1201         /* value is a hsv value: convert to rgb */
1202         if(but->rnaprop) {
1203                 prop= but->rnaprop;
1204
1205                 if(RNA_property_editable(&but->rnapoin, prop)) {
1206                         switch(RNA_property_type(&but->rnapoin, prop)) {
1207                                 case PROP_BOOLEAN:
1208                                         if(RNA_property_array_length(&but->rnapoin, prop))
1209                                                 RNA_property_boolean_set_array(&but->rnapoin, prop, but->rnaindex, value);
1210                                         else
1211                                                 RNA_property_boolean_set(&but->rnapoin, prop, value);
1212                                         break;
1213                                 case PROP_INT:
1214                                         if(RNA_property_array_length(&but->rnapoin, prop))
1215                                                 RNA_property_int_set_array(&but->rnapoin, prop, but->rnaindex, value);
1216                                         else
1217                                                 RNA_property_int_set(&but->rnapoin, prop, value);
1218                                         break;
1219                                 case PROP_FLOAT:
1220                                         if(RNA_property_array_length(&but->rnapoin, prop))
1221                                                 RNA_property_float_set_array(&but->rnapoin, prop, but->rnaindex, value);
1222                                         else
1223                                                 RNA_property_float_set(&but->rnapoin, prop, value);
1224                                         break;
1225                                 case PROP_ENUM:
1226                                         RNA_property_enum_set(&but->rnapoin, prop, value);
1227                                         break;
1228                                 default:
1229                                         break;
1230                         }
1231                 }
1232         }
1233         else if(but->pointype==0);
1234         else if(but->type==HSVSLI ) {
1235                 float h, s, v, *fp;
1236                 
1237                 fp= (but->editvec)? but->editvec: (float *)but->poin;
1238                 rgb_to_hsv(fp[0], fp[1], fp[2], &h, &s, &v);
1239                 
1240                 switch(but->str[0]) {
1241                 case 'H': h= value; break;
1242                 case 'S': s= value; break;
1243                 case 'V': v= value; break;
1244                 }
1245                 
1246                 hsv_to_rgb(h, s, v, fp, fp+1, fp+2);
1247                 
1248         }
1249         else {
1250                 /* first do rounding */
1251                 if(but->pointype==CHA)
1252                         value= (char)floor(value+0.5);
1253                 else if(but->pointype==SHO ) {
1254                         /* gcc 3.2.1 seems to have problems 
1255                          * casting a double like 32772.0 to
1256                          * a short so we cast to an int, then 
1257                          to a short */
1258                         int gcckludge;
1259                         gcckludge = (int) floor(value+0.5);
1260                         value= (short)gcckludge;
1261                 }
1262                 else if(but->pointype==INT )
1263                         value= (int)floor(value+0.5);
1264                 else if(but->pointype==FLO ) {
1265                         float fval= (float)value;
1266                         if(fval>= -0.00001f && fval<= 0.00001f) fval= 0.0f;     /* prevent negative zero */
1267                         value= fval;
1268                 }
1269                 
1270                 /* then set value with possible edit override */
1271                 if(but->editval)
1272                         *but->editval= value;
1273                 else if(but->pointype==CHA)
1274                         *((char *)but->poin)= (char)value;
1275                 else if(but->pointype==SHO)
1276                         *((short *)but->poin)= (short)value;
1277                 else if(but->pointype==INT)
1278                         *((int *)but->poin)= (int)value;
1279                 else if(but->pointype==FLO)
1280                         *((float *)but->poin)= (float)value;
1281         }
1282
1283         /* update select flag */
1284         ui_is_but_sel(but);
1285 }
1286
1287 void ui_get_but_string(uiBut *but, char *str, int maxlen)
1288 {
1289         if(but->rnaprop) {
1290                 char *buf;
1291                 
1292                 buf= RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen);
1293
1294                 if(buf != str) {
1295                         /* string was too long, we have to truncate */
1296                         BLI_strncpy(str, buf, maxlen);
1297                         MEM_freeN(buf);
1298                 }
1299         }
1300         else
1301                 BLI_strncpy(str, but->poin, maxlen);
1302
1303 }
1304
1305 void ui_set_but_string(uiBut *but, const char *str)
1306 {
1307         if(but->rnaprop) {
1308                 if(RNA_property_editable(&but->rnapoin, but->rnaprop))
1309                         RNA_property_string_set(&but->rnapoin, but->rnaprop, str);
1310         }
1311         else
1312                 BLI_strncpy(but->poin, str, but->max);
1313 }
1314
1315 /* ******************* Font ********************/
1316
1317 static void ui_set_ftf_font(float aspect)
1318 {
1319 #ifdef INTERNATIONAL
1320         if(aspect<1.15) {
1321                 FTF_SetFontSize('l');
1322         }
1323         else if(aspect<1.59) {
1324                 FTF_SetFontSize('m');
1325         }
1326         else {
1327                 FTF_SetFontSize('s');
1328         }
1329 #endif
1330 }
1331
1332 void uiSetCurFont(uiBlock *block, int index)
1333 {
1334         ui_set_ftf_font(block->aspect);
1335         
1336         if(block->aspect<0.60) {
1337                 block->curfont= UIfont[index].xl;
1338         }
1339         else if(block->aspect<1.15) {
1340                 block->curfont= UIfont[index].large;
1341         }
1342         else if(block->aspect<1.59) {
1343                 block->curfont= UIfont[index].medium;           
1344         }
1345         else {
1346                 block->curfont= UIfont[index].small;            
1347         }
1348
1349         if(block->curfont==NULL) block->curfont= UIfont[index].large;   
1350         if(block->curfont==NULL) block->curfont= UIfont[index].medium;  
1351         if(block->curfont==NULL) printf("error block no font %s\n", block->name);
1352         
1353 }
1354
1355 /* called by node editor */
1356 void *uiSetCurFont_ext(float aspect)
1357 {
1358         void *curfont;
1359         
1360         ui_set_ftf_font(aspect);
1361         
1362         if(aspect<0.60) {
1363                 curfont= UIfont[0].xl;
1364         }
1365         else if(aspect<1.15) {
1366                 curfont= UIfont[0].large;
1367         }
1368         else if(aspect<1.59) {
1369                 curfont= UIfont[0].medium;              
1370         }
1371         else {
1372                 curfont= UIfont[0].small;               
1373         }
1374         
1375         if(curfont==NULL) curfont= UIfont[0].large;     
1376         if(curfont==NULL) curfont= UIfont[0].medium;    
1377         
1378         return curfont;
1379 }
1380
1381 void uiDefFont(unsigned int index, void *xl, void *large, void *medium, void *small)
1382 {
1383         if(index>=UI_ARRAY) return;
1384         
1385         UIfont[index].xl= xl;
1386         UIfont[index].large= large;
1387         UIfont[index].medium= medium;
1388         UIfont[index].small= small;
1389 }
1390
1391 /* ******************* Free ********************/
1392
1393 static void ui_free_link(uiLink *link)
1394 {
1395         if(link) {      
1396                 BLI_freelistN(&link->lines);
1397                 MEM_freeN(link);
1398         }
1399 }
1400
1401 static void ui_free_but(const bContext *C, uiBut *but)
1402 {
1403         if(but->opptr) {
1404                 WM_operator_properties_free(but->opptr);
1405                 MEM_freeN(but->opptr);
1406         }
1407         if(but->active) ui_button_active_cancel(C, but);
1408         if(but->str && but->str != but->strdata) MEM_freeN(but->str);
1409         ui_free_link(but->link);
1410
1411         MEM_freeN(but);
1412 }
1413
1414 void uiFreeBlock(const bContext *C, uiBlock *block)
1415 {
1416         uiBut *but;
1417
1418         while( (but= block->buttons.first) ) {
1419                 BLI_remlink(&block->buttons, but);      
1420                 ui_free_but(C, but);
1421         }
1422
1423         if(block->panel) {
1424                 block->panel->active= 0;
1425         }
1426         BLI_freelistN(&block->saferct);
1427         
1428         MEM_freeN(block);
1429 }
1430
1431 void uiFreeBlocks(const bContext *C, ListBase *lb)
1432 {
1433         uiBlock *block;
1434         
1435         while( (block= lb->first) ) {
1436                 BLI_remlink(lb, block);
1437                 uiFreeBlock(C, block);
1438         }
1439 }
1440
1441 void uiFreeInactiveBlocks(const bContext *C, ListBase *lb)
1442 {
1443         uiBlock *block, *nextblock;
1444
1445         for(block=lb->first; block; block=nextblock) {
1446                 nextblock= block->next;
1447         
1448                 if(!block->handle) {
1449                         if(!block->active) {
1450                                 BLI_remlink(lb, block);
1451                                 uiFreeBlock(C, block);
1452                         }
1453                         else
1454                                 block->active= 0;
1455                 }
1456         }
1457 }
1458
1459 uiBlock *uiBeginBlock(const bContext *C, ARegion *region, char *name, short dt, short font)
1460 {
1461         ListBase *lb;
1462         uiBlock *block, *oldblock= NULL;
1463         wmWindow *window;
1464         int getsizex, getsizey;
1465
1466         window= CTX_wm_window(C);
1467         lb= &region->uiblocks;
1468         
1469         /* each listbase only has one block with this name, free block
1470          * if is already there so it can be rebuilt from scratch */
1471         if(lb) {
1472                 for (oldblock= lb->first; oldblock; oldblock= oldblock->next)
1473                         if (BLI_streq(oldblock->name, name))
1474                                 break;
1475
1476                 if (oldblock) {
1477                         oldblock->active= 0;
1478                         oldblock->panel= NULL;
1479                 }
1480         }
1481         
1482         block= MEM_callocN(sizeof(uiBlock), "uiBlock");
1483         block->oldblock= oldblock;
1484         block->active= 1;
1485
1486         /* at the beginning of the list! for dynamical menus/blocks */
1487         if(lb)
1488                 BLI_addhead(lb, block);
1489
1490         BLI_strncpy(block->name, name, sizeof(block->name));
1491
1492 #if 0
1493         /* draw win */
1494         block->win= win;
1495         /* window where queue event should be added, pretty weak this way!
1496            this is because the 'mainwin' pup menu's */
1497         block->winq= mywinget();
1498 #endif
1499
1500         block->dt= dt;
1501         block->themecol= TH_AUTO;
1502
1503         /* window matrix and aspect */
1504         if(region->swinid) {
1505                 wm_subwindow_getmatrix(window, region->swinid, block->winmat);
1506                 wm_subwindow_getsize(window, region->swinid, &getsizex, &getsizey);
1507
1508                 /* TODO - investigate why block->winmat[0][0] is negative
1509                  * in the image view when viewRedrawForce is called */
1510                 block->aspect= 2.0/fabs( (getsizex)*block->winmat[0][0]);
1511         }
1512         else {
1513                 /* no subwindow created yet, for menus for example, so we
1514                  * use the main window instead, since buttons are created
1515                  * there anyway */
1516                 wm_subwindow_getmatrix(window, window->winid, block->winmat);
1517                 wm_subwindow_getsize(window, window->winid, &getsizex, &getsizey);
1518
1519                 block->aspect= 2.0/fabs(getsizex*block->winmat[0][0]);
1520                 block->auto_open= 2;
1521                 block->flag |= UI_BLOCK_LOOP; /* tag as menu */
1522         }
1523
1524         uiSetCurFont(block, font);
1525
1526         return block;
1527 }
1528
1529 uiBlock *uiGetBlock(char *name, ARegion *ar)
1530 {
1531         uiBlock *block= ar->uiblocks.first;
1532         
1533         while(block) {
1534                 if( strcmp(name, block->name)==0 ) return block;
1535                 block= block->next;
1536         }
1537         
1538         return NULL;
1539 }
1540
1541 void ui_check_but(uiBut *but)
1542 {
1543         /* if something changed in the button */
1544         ID *id;
1545         double value;
1546         float okwidth;
1547         int transopts= ui_translate_buttons();
1548         short pos;
1549         
1550         ui_is_but_sel(but);
1551         
1552         if(but->type==TEX || but->type==IDPOIN) transopts= 0;
1553
1554         /* test for min and max, icon sliders, etc */
1555         switch( but->type ) {
1556                 case NUM:
1557                 case SLI:
1558                 case SCROLL:
1559                 case NUMSLI:
1560                 case HSVSLI:
1561                         value= ui_get_but_val(but);
1562                         if(value < but->min) ui_set_but_val(but, but->min);
1563                         else if(value > but->max) ui_set_but_val(but, but->max);
1564                         break;
1565                         
1566                 case NUMABS:
1567                         value= fabs( ui_get_but_val(but) );
1568                         if(value < but->min) ui_set_but_val(but, but->min);
1569                         else if(value > but->max) ui_set_but_val(but, but->max);
1570                         break;
1571                         
1572                 case ICONTOG: 
1573                 case ICONTOGN:
1574                         if(but->flag & UI_SELECT) but->iconadd= 1;
1575                         else but->iconadd= 0;
1576                         break;
1577                         
1578                 case ICONROW:
1579                         value= ui_get_but_val(but);
1580                         but->iconadd= (int)value- (int)(but->min);
1581                         break;
1582                         
1583                 case ICONTEXTROW:
1584                         value= ui_get_but_val(but);
1585                         but->iconadd= (int)value- (int)(but->min);
1586                         break;
1587         }
1588         
1589         
1590         /* safety is 4 to enable small number buttons (like 'users') */
1591         if(but->type==NUMSLI || but->type==HSVSLI) 
1592                 okwidth= -4 + (but->x2 - but->x1)/2.0;
1593         else 
1594                 okwidth= -4 + (but->x2 - but->x1); 
1595         
1596         /* name: */
1597         switch( but->type ) {
1598         
1599         case MENU:
1600         case ICONTEXTROW:
1601                 
1602                 if(but->x2 - but->x1 > 24) {
1603                         value= ui_get_but_val(but);
1604                         ui_set_name_menu(but, (int)value);
1605                 }
1606                 break;
1607         
1608         case NUM:
1609         case NUMSLI:
1610         case HSVSLI:
1611         case NUMABS:
1612
1613                 value= ui_get_but_val(but);
1614
1615                 if(ui_is_but_float(but)) {
1616                         if(value == FLT_MAX) sprintf(but->drawstr, "%sinf", but->str);
1617                         else if(value == -FLT_MAX) sprintf(but->drawstr, "%s-inf", but->str);
1618                         else if(but->a2) { /* amount of digits defined */
1619                                 if(but->a2==1) sprintf(but->drawstr, "%s%.1f", but->str, value);
1620                                 else if(but->a2==2) sprintf(but->drawstr, "%s%.2f", but->str, value);
1621                                 else if(but->a2==3) sprintf(but->drawstr, "%s%.3f", but->str, value);
1622                                 else sprintf(but->drawstr, "%s%.4f", but->str, value);
1623                         }
1624                         else {
1625                                 if(but->max<10.001) sprintf(but->drawstr, "%s%.3f", but->str, value);
1626                                 else sprintf(but->drawstr, "%s%.2f", but->str, value);
1627                         }
1628                 }
1629                 else {
1630                         sprintf(but->drawstr, "%s%d", but->str, (int)value);
1631                 }
1632                 break;
1633
1634         case LABEL:
1635                 if(ui_is_but_float(but)) {
1636                         value= ui_get_but_val(but);
1637                         if(but->a2) { /* amount of digits defined */
1638                                 if(but->a2==1) sprintf(but->drawstr, "%s%.1f", but->str, value);
1639                                 else if(but->a2==2) sprintf(but->drawstr, "%s%.2f", but->str, value);
1640                                 else if(but->a2==3) sprintf(but->drawstr, "%s%.3f", but->str, value);
1641                                 else sprintf(but->drawstr, "%s%.4f", but->str, value);
1642                         }
1643                         else {
1644                                 sprintf(but->drawstr, "%s%.2f", but->str, value);
1645                         }
1646                 }
1647                 else strcpy(but->drawstr, but->str);
1648                 
1649                 break;
1650
1651         case IDPOIN:
1652                 id= *(but->idpoin_idpp);
1653                 strcpy(but->drawstr, but->str);
1654                 if(id) strcat(but->drawstr, id->name+2);
1655                 break;
1656         
1657         case TEX:
1658                 if(!but->editstr) {
1659                         char str[UI_MAX_DRAW_STR];
1660
1661                         ui_get_but_string(but, str, UI_MAX_DRAW_STR-strlen(but->str));
1662
1663                         strcpy(but->drawstr, but->str);
1664                         strcat(but->drawstr, str);
1665                 }
1666                 break;
1667         
1668         case KEYEVT:
1669                 strcpy(but->drawstr, but->str);
1670                 if (but->flag & UI_SELECT) {
1671                         strcat(but->drawstr, "Press a key");
1672                 } else {
1673                         strcat(but->drawstr, WM_key_event_string((short) ui_get_but_val(but)));
1674                 }
1675                 break;
1676
1677         case BUT_TOGDUAL:
1678                 /* trying to get the dual-icon to left of text... not very nice */
1679                 if(but->str[0]) {
1680                         strcpy(but->drawstr, "  ");
1681                         strcpy(but->drawstr+2, but->str);
1682                 }
1683                 break;
1684         default:
1685                 strcpy(but->drawstr, but->str);
1686                 
1687         }
1688
1689         /* if we are doing text editing, this will override the drawstr */
1690         if(but->editstr) {
1691                 strcpy(but->drawstr, but->str);
1692                 strcat(but->drawstr, but->editstr);
1693         }
1694
1695         if(but->drawstr[0]) {
1696                 but->strwidth= but->aspect*UI_GetStringWidth(but->font, but->drawstr, transopts);
1697                 // here should be check for less space for icon offsets...
1698                 if(but->type==MENU) okwidth -= 15;
1699         }
1700         else
1701                 but->strwidth= 0;
1702
1703                 /* automatic width */
1704         if(but->x2==0.0f && but->x1 > 0.0f) {
1705                 but->x2= (but->x1+but->strwidth+6); 
1706         }
1707
1708         if(but->strwidth==0) but->drawstr[0]= 0;
1709         else if(but->block->flag & UI_BLOCK_LOOP);      // no clip string, uiTextBoundsBlock is used (hack!)
1710         else {
1711
1712                 /* calc but->ofs, to draw the string shorter if too long */
1713                 but->ofs= 0;
1714
1715                 while(but->strwidth > (int)okwidth ) {
1716         
1717                         if ELEM3(but->type, NUM, NUMABS, TEX) { // only these cut off left
1718                                 but->ofs++;
1719                                 but->strwidth= but->aspect*UI_GetStringWidth(but->font, but->drawstr+but->ofs, transopts);
1720                                 
1721                                 /* textbut exception */
1722                                 if(but->editstr && but->pos != -1) {
1723                                         pos= but->pos+strlen(but->str);
1724                                         if(pos-1 < but->ofs) {
1725                                                 pos= but->ofs-pos+1;
1726                                                 but->ofs -= pos;
1727                                                 if(but->ofs<0) {
1728                                                         but->ofs= 0;
1729                                                         pos--;
1730                                                 }
1731                                                 but->drawstr[ strlen(but->drawstr)-pos ]= 0;
1732                                         }
1733                                 }
1734                         }
1735                         else {
1736                                 but->drawstr[ strlen(but->drawstr)-1 ]= 0;
1737                                 but->strwidth= but->aspect*UI_GetStringWidth(but->font, but->drawstr, transopts);
1738                         }
1739                         
1740                         if(but->strwidth < 10) break;
1741                 }
1742         }
1743 }
1744
1745 static int ui_auto_themecol(uiBut *but)
1746 {
1747         if(but->block->flag & UI_BLOCK_LOOP)
1748                 return TH_MENU_ITEM;
1749
1750         switch(but->type) {
1751         case BUT:
1752                 return TH_BUT_ACTION;
1753         case ROW:
1754         case TOG:
1755         case TOG3:
1756         case TOGR:
1757         case TOGN:
1758         case BUT_TOGDUAL:
1759                 return TH_BUT_SETTING;
1760         case SLI:
1761         case NUM:
1762         case NUMSLI:
1763         case NUMABS:
1764         case HSVSLI:
1765                 return TH_BUT_NUM;
1766         case TEX:
1767                 return TH_BUT_TEXTFIELD;
1768         case PULLDOWN:
1769         case BLOCK:
1770         case MENU:
1771         case BUTM:
1772                 return TH_BUT_POPUP;
1773         case ROUNDBOX:
1774                 return TH_PANEL;
1775         default:
1776                 return TH_BUT_NEUTRAL;
1777         }
1778 }
1779
1780 void uiBlockBeginAlign(uiBlock *block)
1781 {
1782         /* if other align was active, end it */
1783         if(block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block);
1784
1785         block->flag |= UI_BUT_ALIGN_DOWN;       
1786         /* buttons declared after this call will this align flag */
1787 }
1788
1789 static int buts_are_horiz(uiBut *but1, uiBut *but2)
1790 {
1791         float dx, dy;
1792         
1793         dx= fabs( but1->x2 - but2->x1);
1794         dy= fabs( but1->y1 - but2->y2);
1795         
1796         if(dx > dy) return 0;
1797         return 1;
1798 }
1799
1800 void uiBlockEndAlign(uiBlock *block)
1801 {
1802         uiBut *prev, *but=NULL, *next;
1803         int flag= 0, cols=0, rows=0;
1804         int theme= UI_GetThemeValue(TH_BUT_DRAWTYPE);
1805         
1806         if ( !(ELEM4(theme, TH_MINIMAL, TH_SHADED, TH_ROUNDED, TH_ROUNDSHADED)) ) {
1807                 block->flag &= ~UI_BUT_ALIGN;   // all 4 flags
1808                 return;
1809         }
1810         
1811         /* auto align:
1812                 - go back to first button of align start (ALIGN_DOWN)
1813                 - compare triples, and define flags
1814         */
1815         prev= block->buttons.last;
1816         while(prev) {
1817                 if( (prev->flag & UI_BUT_ALIGN_DOWN)) but= prev;
1818                 else break;
1819                 
1820                 if(but && but->next) {
1821                         if(buts_are_horiz(but, but->next)) cols++;
1822                         else rows++;
1823                 }
1824                 
1825                 prev= prev->prev;
1826         }
1827         if(but==NULL) return;
1828         
1829         /* rows==0: 1 row, cols==0: 1 collumn */
1830         
1831         /* note;  how it uses 'flag' in loop below (either set it, or OR it) is confusing */
1832         prev= NULL;
1833         while(but) {
1834                 next= but->next;
1835                 
1836                 /* clear old flag */
1837                 but->flag &= ~UI_BUT_ALIGN_DOWN;
1838                 
1839                 if(flag==0) {   /* first case */
1840                         if(next) {
1841                                 if(buts_are_horiz(but, next)) {
1842                                         if(rows==0)
1843                                                 flag= UI_BUT_ALIGN_RIGHT;
1844                                         else 
1845                                                 flag= UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT;
1846                                 }
1847                                 else {
1848                                         flag= UI_BUT_ALIGN_DOWN;
1849                                 }
1850                         }
1851                 }
1852                 else if(next==NULL) {   /* last case */
1853                         if(prev) {
1854                                 if(buts_are_horiz(prev, but)) {
1855                                         if(rows==0) 
1856                                                 flag= UI_BUT_ALIGN_LEFT;
1857                                         else
1858                                                 flag= UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT;
1859                                 }
1860                                 else flag= UI_BUT_ALIGN_TOP;
1861                         }
1862                 }
1863                 else if(buts_are_horiz(but, next)) {
1864                         /* check if this is already second row */
1865                         if( prev && buts_are_horiz(prev, but)==0) {
1866                                 flag |= UI_BUT_ALIGN_TOP;
1867                                 /* exception case: bottom row */
1868                                 if(rows>0) {
1869                                         uiBut *bt= but;
1870                                         while(bt) {
1871                                                 if(bt->next && buts_are_horiz(bt, bt->next)==0 ) break; 
1872                                                 bt= bt->next;
1873                                         }
1874                                         if(bt==0) flag= UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT;
1875                                 }
1876                         }
1877                         else flag |= UI_BUT_ALIGN_LEFT;
1878                 }
1879                 else {
1880                         if(cols==0) {
1881                                 flag |= UI_BUT_ALIGN_TOP;
1882                         }
1883                         else {  /* next button switches to new row */
1884                                 if( (flag & UI_BUT_ALIGN_TOP)==0) {     /* stil top row */
1885                                         if(prev)
1886                                                 flag= UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT;
1887                                         else 
1888                                                 flag |= UI_BUT_ALIGN_DOWN;
1889                                 }
1890                                 else 
1891                                         flag |= UI_BUT_ALIGN_TOP;
1892                         }
1893                 }
1894                 
1895                 but->flag |= flag;
1896                 
1897                 /* merge coordinates */
1898                 if(prev) {
1899                         // simple cases 
1900                         if(rows==0) {
1901                                 but->x1= (prev->x2+but->x1)/2.0;
1902                                 prev->x2= but->x1;
1903                         }
1904                         else if(cols==0) {
1905                                 but->y2= (prev->y1+but->y2)/2.0;
1906                                 prev->y1= but->y2;
1907                         }
1908                         else {
1909                                 if(buts_are_horiz(prev, but)) {
1910                                         but->x1= (prev->x2+but->x1)/2.0;
1911                                         prev->x2= but->x1;
1912                                         /* copy height too */
1913                                         but->y2= prev->y2;
1914                                 }
1915                                 else if(prev->prev && buts_are_horiz(prev->prev, prev)==0) {
1916                                         /* the previous button is a single one in its row */
1917                                         but->y2= (prev->y1+but->y2)/2.0;
1918                                         prev->y1= but->y2;
1919                                 }
1920                                 else {
1921                                         /* the previous button is not a single one in its row */
1922                                         but->y2= prev->y1;
1923                                 }
1924                         }
1925                 }
1926                 
1927                 prev= but;
1928                 but= next;
1929         }
1930         
1931         block->flag &= ~UI_BUT_ALIGN;   // all 4 flags
1932 }
1933
1934 #if 0
1935 static void uiBlockEndAligno(uiBlock *block)
1936 {
1937         uiBut *but;
1938         
1939         /* correct last defined button */
1940         but= block->buttons.last;
1941         if(but) {
1942                 /* vertical align case */
1943                 if( (block->flag & UI_BUT_ALIGN) == (UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_DOWN) ) {
1944                         but->flag &= ~UI_BUT_ALIGN_DOWN;
1945                 }
1946                 /* horizontal align case */
1947                 if( (block->flag & UI_BUT_ALIGN) == (UI_BUT_ALIGN_LEFT|UI_BUT_ALIGN_RIGHT) ) {
1948                         but->flag &= ~UI_BUT_ALIGN_RIGHT;
1949                 }
1950                 /* else do nothing, manually provided flags */
1951         }
1952         block->flag &= ~UI_BUT_ALIGN;   // all 4 flags
1953 }
1954 #endif
1955
1956 /*
1957 ui_def_but is the function that draws many button types
1958
1959 for float buttons:
1960         "a1" Click Step (how much to change the value each click)
1961         "a2" Number of decimal point values to display. 0 defaults to 3 (0.000) 1,2,3, and a maximum of 4,
1962        all greater values will be clamped to 4.
1963
1964 */
1965 static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  char *tip)
1966 {
1967         uiBut *but;
1968         short slen;
1969         
1970         if(type & BUTPOIN) {            /* a pointer is required */
1971                 if(poin==NULL) {
1972                         /* if pointer is zero, button is removed and not drawn */
1973                         UI_ThemeColor(block->themecol);
1974                         glRects(x1,  y1,  x1+x2,  y1+y2);
1975                         return NULL;
1976                 }
1977         }
1978
1979         but= MEM_callocN(sizeof(uiBut), "uiBut");
1980
1981         but->type= type & BUTTYPE;
1982         but->pointype= type & BUTPOIN;
1983         but->bit= type & BIT;
1984         but->bitnr= type & 31;
1985         but->icon = 0;
1986
1987         BLI_addtail(&block->buttons, but);
1988
1989         but->retval= retval;
1990         if( strlen(str)>=UI_MAX_NAME_STR-1 ) {
1991                 but->str= MEM_callocN( strlen(str)+2, "uiDefBut");
1992                 strcpy(but->str, str);
1993         }
1994         else {
1995                 but->str= but->strdata;
1996                 strcpy(but->str, str);
1997         }
1998         but->x1= x1; 
1999         but->y1= y1;
2000         if(block->autofill) {
2001                 but->x2= x2; 
2002                 but->y2= y2;
2003         }
2004         else {
2005                 but->x2= (x1+x2); 
2006                 but->y2= (y1+y2);
2007         }
2008         but->poin= poin;
2009         but->min= min; 
2010         but->max= max;
2011         but->a1= a1; 
2012         but->a2= a2;
2013         but->tip= tip;
2014         
2015         but->font= block->curfont;
2016         
2017         but->lock= block->lock;
2018         but->lockstr= block->lockstr;
2019
2020         but->aspect= block->aspect;
2021         but->win= block->win;
2022         but->block= block;              // pointer back, used for frontbuffer status, and picker
2023
2024         if(block->themecol==TH_AUTO) but->themecol= ui_auto_themecol(but);
2025         else but->themecol= block->themecol;
2026
2027         but->func= block->func;
2028         but->func_arg1= block->func_arg1;
2029         but->func_arg2= block->func_arg2;
2030         
2031         ui_set_embossfunc(but, block->dt);
2032         
2033         but->pos= -1;   /* cursor invisible */
2034
2035         if(ELEM(but->type, NUM, NUMABS)) {      /* add a space to name */
2036                 slen= strlen(but->str);
2037                 if(slen>0 && slen<UI_MAX_NAME_STR-2) {
2038                         if(but->str[slen-1]!=' ') {
2039                                 but->str[slen]= ' ';
2040                                 but->str[slen+1]= 0;
2041                         }
2042                 }
2043         }
2044         
2045         if(but->type==HSVCUBE) { /* hsv buttons temp storage */
2046                 float rgb[3];
2047                 ui_get_but_vectorf(but, rgb);
2048                 rgb_to_hsv(rgb[0], rgb[1], rgb[2], but->hsv, but->hsv+1, but->hsv+2);
2049         }
2050
2051         if((block->flag & UI_BLOCK_LOOP) || ELEM8(but->type, HSVSLI , NUMSLI, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM)) {
2052                 but->flag |= UI_TEXT_LEFT;
2053         }
2054         
2055         if(but->type==BUT_TOGDUAL) {
2056                 but->flag |= UI_ICON_LEFT;
2057         }
2058
2059         if(but->type==ROUNDBOX)
2060                 but->flag |= UI_NO_HILITE;
2061
2062         but->flag |= (block->flag & UI_BUT_ALIGN);
2063         if(block->flag & UI_BLOCK_NO_HILITE)
2064                 but->flag |= UI_NO_HILITE;
2065
2066         if (but->lock) {
2067                 if (but->lockstr) {
2068                         but->flag |= UI_BUT_DISABLED;
2069                 }
2070         }
2071
2072         return but;
2073 }
2074
2075 uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2,  char *tip)
2076 {
2077         uiBut *but;
2078         PropertyRNA *prop;
2079         PropertyType proptype;
2080         int freestr= 0;
2081
2082         prop= RNA_struct_find_property(ptr, propname);
2083
2084         if(prop) {
2085                 proptype= RNA_property_type(ptr, prop);
2086
2087                 /* use rna values if parameters are not specified */
2088                 if(!str) {
2089                         if(type == MENU && proptype == PROP_ENUM) {
2090                                 const EnumPropertyItem *item;
2091                                 DynStr *dynstr;
2092                                 int i, totitem;
2093
2094                                 RNA_property_enum_items(ptr, prop, &item, &totitem);
2095
2096                                 dynstr= BLI_dynstr_new();
2097                                 BLI_dynstr_appendf(dynstr, "%s%%t", RNA_property_ui_name(ptr, prop));
2098                                 for(i=0; i<totitem; i++)
2099                                         BLI_dynstr_appendf(dynstr, "|%s %%x%d", item[i].name, item[i].value);
2100                                 str= BLI_dynstr_get_cstring(dynstr);
2101                                 BLI_dynstr_free(dynstr);
2102
2103                                 freestr= 1;
2104                         }
2105                         else
2106                                 str= (char*)RNA_property_ui_name(ptr, prop);
2107                 }
2108
2109                 if(!tip) {
2110                         if(type == ROW && proptype == PROP_ENUM) {
2111                                 const EnumPropertyItem *item;
2112                                 int i, totitem;
2113
2114                                 RNA_property_enum_items(ptr, prop, &item, &totitem);
2115
2116                                 for(i=0; i<totitem; i++) {
2117                                         if(item[i].value == (int)max) {
2118                                                 if(item[i].description[0])
2119                                                         tip= (char*)item[i].description;
2120                                                 break;
2121                                         }
2122                                 }
2123                         }
2124                 }
2125                 
2126                 if(!tip)
2127                         tip= (char*)RNA_property_ui_description(ptr, prop);
2128
2129                 if(min == max || a1 == -1 || a2 == -1) {
2130                         if(proptype == PROP_INT) {
2131                                 int softmin, softmax, step;
2132
2133                                 RNA_property_int_ui_range(ptr, prop, &softmin, &softmax, &step);
2134
2135                                 if(min == max) {
2136                                         min= softmin;
2137                                         max= softmax;
2138                                 }
2139                                 if(a1 == -1)
2140                                         a1= step;
2141                                 if(a2 == -1)
2142                                         a2= 0;
2143                         }
2144                         else if(proptype == PROP_FLOAT) {
2145                                 float softmin, softmax, step, precision;
2146
2147                                 RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
2148
2149                                 if(min == max) {
2150                                         min= softmin;
2151                                         max= softmax;
2152                                 }
2153                                 if(a1 == -1)
2154                                         a1= step;
2155                                 if(a2 == -1)
2156                                         a2= precision;
2157                         }
2158                         else if(proptype == PROP_STRING) {
2159                                 min= 0;
2160                                 max= RNA_property_string_maxlength(ptr, prop);
2161                                 if(max == 0) /* interface code should ideally support unlimited length */
2162                                         max= UI_MAX_DRAW_STR; 
2163                         }
2164                 }
2165         }
2166         else
2167                 str= (char*)propname;
2168
2169         /* now create button */
2170         but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, NULL, min, max, a1, a2, tip);
2171
2172         if(prop) {
2173                 but->rnapoin= *ptr;
2174                 but->rnaprop= prop;
2175                 but->rnaindex= index;
2176         }
2177         
2178         if (!prop || !RNA_property_editable(&but->rnapoin, prop)) {
2179                 but->flag |= UI_BUT_DISABLED;
2180                 but->lock = 1;
2181                 but->lockstr = "";
2182         }
2183
2184         if(freestr)
2185                 MEM_freeN(str);
2186         
2187         return but;
2188 }
2189
2190 uiBut *ui_def_but_operator(uiBlock *block, int type, char *opname, int opcontext, char *str, short x1, short y1, short x2, short y2, char *tip)
2191 {
2192         uiBut *but;
2193         wmOperatorType *ot;
2194         
2195         ot= WM_operatortype_find(opname);
2196
2197         if(!str) {
2198                 if(ot) str= ot->name;
2199                 else str= opname;
2200         }
2201
2202         but= ui_def_but(block, type, -1, str, x1, y1, x2, y2, NULL, 0, 0, 0, 0, tip);
2203         but->opname= opname;
2204         but->opcontext= opcontext;
2205
2206         if(!ot) {
2207                 but->flag |= UI_BUT_DISABLED;
2208                 but->lock = 1;
2209                 but->lockstr = "";
2210         }
2211
2212         return but;
2213 }
2214
2215 uiBut *uiDefBut(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  char *tip)
2216 {
2217         uiBut *but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
2218
2219         ui_check_but(but);
2220         
2221         return but;
2222 }
2223
2224         /* if _x_ is a power of two (only one bit) return the power,
2225          * otherwise return -1. 
2226          * (1<<findBitIndex(x))==x for powers of two.
2227          */
2228 static int findBitIndex(unsigned int x) {
2229         if (!x || (x&(x-1))!=0) {       /* x&(x-1) strips lowest bit */
2230                 return -1;
2231         } else {
2232                 int idx= 0;
2233
2234                 if (x&0xFFFF0000)       idx+=16, x>>=16;
2235                 if (x&0xFF00)           idx+=8, x>>=8;
2236                 if (x&0xF0)                     idx+=4, x>>=4;
2237                 if (x&0xC)                      idx+=2, x>>=2;
2238                 if (x&0x2)                      idx+=1;
2239
2240                 return idx;
2241         }
2242 }
2243
2244 /* autocomplete helper functions */
2245 struct AutoComplete {
2246         int maxlen;
2247         char *truncate;
2248         char *startname;
2249 };
2250
2251 AutoComplete *autocomplete_begin(char *startname, int maxlen)
2252 {
2253         AutoComplete *autocpl;
2254         
2255         autocpl= MEM_callocN(sizeof(AutoComplete), "AutoComplete");
2256         autocpl->maxlen= maxlen;
2257         autocpl->truncate= MEM_callocN(sizeof(char)*maxlen, "AutoCompleteTruncate");
2258         autocpl->startname= startname;
2259
2260         return autocpl;
2261 }
2262
2263 void autocomplete_do_name(AutoComplete *autocpl, const char *name)
2264 {
2265         char *truncate= autocpl->truncate;
2266         char *startname= autocpl->startname;
2267         int a;
2268
2269         for(a=0; a<autocpl->maxlen-1; a++) {
2270                 if(startname[a]==0 || startname[a]!=name[a])
2271                         break;
2272         }
2273         /* found a match */
2274         if(startname[a]==0) {
2275                 /* first match */
2276                 if(truncate[0]==0)
2277                         BLI_strncpy(truncate, name, autocpl->maxlen);
2278                 else {
2279                         /* remove from truncate what is not in bone->name */
2280                         for(a=0; a<autocpl->maxlen-1; a++) {
2281                                 if(truncate[a]!=name[a])
2282                                         truncate[a]= 0;
2283                         }
2284                 }
2285         }
2286 }
2287
2288 void autocomplete_end(AutoComplete *autocpl, char *autoname)
2289 {
2290         if(autocpl->truncate[0])
2291                 BLI_strncpy(autoname, autocpl->truncate, autocpl->maxlen);
2292         else
2293                 BLI_strncpy(autoname, autocpl->startname, autocpl->maxlen);
2294
2295         MEM_freeN(autocpl->truncate);
2296         MEM_freeN(autocpl);
2297 }
2298
2299 /* autocomplete callback for ID buttons */
2300 static void autocomplete_id(bContext *C, char *str, void *arg_v)
2301 {
2302         int blocktype= (intptr_t)arg_v;
2303         ListBase *listb= wich_libbase(CTX_data_main(C), blocktype);
2304         
2305         if(listb==NULL) return;
2306         
2307         /* search if str matches the beginning of an ID struct */
2308         if(str[0]) {
2309                 AutoComplete *autocpl= autocomplete_begin(str, 22);
2310                 ID *id;
2311                 
2312                 for(id= listb->first; id; id= id->next)
2313                         autocomplete_do_name(autocpl, id->name+2);
2314
2315                 autocomplete_end(autocpl, str);
2316         }
2317 }
2318
2319 static uiBut *uiDefButBit(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  char *tip)
2320 {
2321         int bitIdx= findBitIndex(bit);
2322         if (bitIdx==-1) {
2323                 return NULL;
2324         } else {
2325                 return uiDefBut(block, type|BIT|bitIdx, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
2326         }
2327 }
2328 uiBut *uiDefButF(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2,  char *tip)
2329 {
2330         return uiDefBut(block, type|FLO, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2331 }
2332 uiBut *uiDefButBitF(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2,  char *tip)
2333 {
2334         return uiDefButBit(block, type|FLO, bit, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2335 }
2336 uiBut *uiDefButI(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2,  char *tip)
2337 {
2338         return uiDefBut(block, type|INT, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2339 }
2340 uiBut *uiDefButBitI(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2,  char *tip)
2341 {
2342         return uiDefButBit(block, type|INT, bit, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2343 }
2344 uiBut *uiDefButS(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2,  char *tip)
2345 {
2346         return uiDefBut(block, type|SHO, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2347 }
2348 uiBut *uiDefButBitS(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2,  char *tip)
2349 {
2350         return uiDefButBit(block, type|SHO, bit, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2351 }
2352 uiBut *uiDefButC(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2,  char *tip)
2353 {
2354         return uiDefBut(block, type|CHA, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2355 }
2356 uiBut *uiDefButBitC(uiBlock *block, int type, int bit, int retval, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2,  char *tip)
2357 {
2358         return uiDefButBit(block, type|CHA, bit, retval, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2359 }
2360 uiBut *uiDefButR(uiBlock *block, int type, int retval, char *str, short x1, short y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2,  char *tip)
2361 {
2362         uiBut *but;
2363
2364         but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
2365         if(but)
2366                 ui_check_but(but);
2367
2368         return but;
2369 }
2370 uiBut *uiDefButO(uiBlock *block, int type, char *opname, int opcontext, char *str, short x1, short y1, short x2, short y2, char *tip)
2371 {
2372         uiBut *but;
2373
2374         but= ui_def_but_operator(block, type, opname, opcontext, str, x1, y1, x2, y2, tip);
2375         if(but)
2376                 ui_check_but(but);
2377
2378         return but;
2379 }
2380
2381 uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  char *tip)
2382 {
2383         uiBut *but= ui_def_but(block, type, retval, "", x1, y1, x2, y2, poin, min, max, a1, a2, tip);
2384         
2385         but->icon= (BIFIconID) icon;
2386         but->flag|= UI_HAS_ICON;
2387
2388         ui_check_but(but);
2389         
2390         return but;
2391 }
2392 static uiBut *uiDefIconButBit(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  char *tip)
2393 {
2394         int bitIdx= findBitIndex(bit);
2395         if (bitIdx==-1) {
2396                 return NULL;
2397         } else {
2398                 return uiDefIconBut(block, type|BIT|bitIdx, retval, icon, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
2399         }
2400 }
2401
2402 uiBut *uiDefIconButF(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2,  char *tip)
2403 {
2404         return uiDefIconBut(block, type|FLO, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2405 }
2406 uiBut *uiDefIconButBitF(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2,  char *tip)
2407 {
2408         return uiDefIconButBit(block, type|FLO, bit, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2409 }
2410 uiBut *uiDefIconButI(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2,  char *tip)
2411 {
2412         return uiDefIconBut(block, type|INT, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2413 }
2414 uiBut *uiDefIconButBitI(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2,  char *tip)
2415 {
2416         return uiDefIconButBit(block, type|INT, bit, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2417 }
2418 uiBut *uiDefIconButS(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2,  char *tip)
2419 {
2420         return uiDefIconBut(block, type|SHO, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2421 }
2422 uiBut *uiDefIconButBitS(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2,  char *tip)
2423 {
2424         return uiDefIconButBit(block, type|SHO, bit, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2425 }
2426 uiBut *uiDefIconButC(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2,  char *tip)
2427 {
2428         return uiDefIconBut(block, type|CHA, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2429 }
2430 uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, int retval, int icon, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2,  char *tip)
2431 {
2432         return uiDefIconButBit(block, type|CHA, bit, retval, icon, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2433 }
2434 uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, short x1, short y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2,  char *tip)
2435 {
2436         uiBut *but;
2437
2438         but= ui_def_but_rna(block, type, retval, "", x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
2439         if(but) {
2440                 but->icon= (BIFIconID) icon;
2441                 but->flag|= UI_HAS_ICON;
2442                 ui_check_but(but);
2443         }
2444
2445         return but;
2446 }
2447 uiBut *uiDefIconButO(uiBlock *block, int type, char *opname, int opcontext, int icon, short x1, short y1, short x2, short y2, char *tip)
2448 {
2449         uiBut *but;
2450
2451         but= ui_def_but_operator(block, type, opname, opcontext, "", x1, y1, x2, y2, tip);
2452         if(but) {
2453                 but->icon= (BIFIconID) icon;
2454                 but->flag|= UI_HAS_ICON;
2455                 ui_check_but(but);
2456         }
2457
2458         return but;
2459 }
2460
2461 /* Button containing both string label and icon */
2462 uiBut *uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  char *tip)
2463 {
2464         uiBut *but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
2465
2466         but->icon= (BIFIconID) icon;
2467         but->flag|= UI_HAS_ICON;
2468
2469         but->flag|= UI_ICON_LEFT;
2470
2471         ui_check_but(but);
2472
2473         return but;
2474 }
2475 static uiBut *uiDefIconTextButBit(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, void *poin, float min, float max, float a1, float a2,  char *tip)
2476 {
2477         int bitIdx= findBitIndex(bit);
2478         if (bitIdx==-1) {
2479                 return NULL;
2480         } else {
2481                 return uiDefIconTextBut(block, type|BIT|bitIdx, retval, icon, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip);
2482         }
2483 }
2484
2485 uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2,  char *tip)
2486 {
2487         return uiDefIconTextBut(block, type|FLO, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2488 }
2489 uiBut *uiDefIconTextButBitF(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, float min, float max, float a1, float a2,  char *tip)
2490 {
2491         return uiDefIconTextButBit(block, type|FLO, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2492 }
2493 uiBut *uiDefIconTextButI(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2,  char *tip)
2494 {
2495         return uiDefIconTextBut(block, type|INT, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2496 }
2497 uiBut *uiDefIconTextButBitI(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, int *poin, float min, float max, float a1, float a2,  char *tip)
2498 {
2499         return uiDefIconTextButBit(block, type|INT, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2500 }
2501 uiBut *uiDefIconTextButS(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2,  char *tip)
2502 {
2503         return uiDefIconTextBut(block, type|SHO, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2504 }
2505 uiBut *uiDefIconTextButBitS(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, short *poin, float min, float max, float a1, float a2,  char *tip)
2506 {
2507         return uiDefIconTextButBit(block, type|SHO, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2508 }
2509 uiBut *uiDefIconTextButC(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2,  char *tip)
2510 {
2511         return uiDefIconTextBut(block, type|CHA, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2512 }
2513 uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int icon, char *str, short x1, short y1, short x2, short y2, char *poin, float min, float max, float a1, float a2,  char *tip)
2514 {
2515         return uiDefIconTextButBit(block, type|CHA, bit, retval, icon, str, x1, y1, x2, y2, (void*) poin, min, max, a1, a2, tip);
2516 }
2517 uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2,  char *tip)
2518 {
2519         uiBut *but;
2520
2521         but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip);
2522         if(but) {
2523                 but->icon= (BIFIconID) icon;
2524                 but->flag|= UI_HAS_ICON;
2525                 but->flag|= UI_ICON_LEFT;
2526                 ui_check_but(but);
2527         }
2528
2529         return but;
2530 }
2531 uiBut *uiDefIconTextButO(uiBlock *block, int type, char *opname, int opcontext, int icon, char *str, short x1, short y1, short x2, short y2, char *tip)
2532 {
2533         uiBut *but;
2534
2535         but= ui_def_but_operator(block, type, opname, opcontext, str, x1, y1, x2, y2, tip);
2536         if(but) {
2537                 but->icon= (BIFIconID) icon;
2538                 but->flag|= UI_HAS_ICON;
2539                 but->flag|= UI_ICON_LEFT;
2540                 ui_check_but(but);
2541         }
2542
2543         return but;
2544 }
2545
2546 static int ui_menu_y(uiBlock *block)
2547 {
2548         uiBut *but= block->buttons.last;
2549
2550         if(but) return but->y1;
2551         else return 0;
2552 }
2553
2554 uiBut *uiDefMenuButO(uiBlock *block, char *opname, char *name)
2555 {
2556         int y= ui_menu_y(block) - MENU_ITEM_HEIGHT;
2557         return uiDefIconTextButO(block, BUT, opname, WM_OP_INVOKE_REGION_WIN, ICON_BLANK1, name, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT-1, NULL);
2558 }
2559
2560 uiBut *uiDefMenuSep(uiBlock *block)
2561 {
2562         int y= ui_menu_y(block) - MENU_SEP_HEIGHT;
2563         return uiDefBut(block, SEPR, 0, "", 0, y, MENU_WIDTH, MENU_SEP_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
2564 }
2565
2566 uiBut *uiDefMenuSub(uiBlock *block, uiBlockFuncFP func, char *name)
2567 {
2568         int y= ui_menu_y(block) - MENU_ITEM_HEIGHT;
2569         return uiDefIconTextBlockBut(block, func, NULL, ICON_RIGHTARROW_THIN, name, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT-1, "");
2570 }
2571
2572 uiBut *uiDefMenuTogR(uiBlock *block, PointerRNA *ptr, char *propname, char *propvalue, char *name)
2573 {
2574         uiBut *but;
2575         PropertyRNA *prop;
2576         PropertyType type;
2577         const EnumPropertyItem *item;
2578         int a, value, totitem, icon= ICON_CHECKBOX_DEHLT;
2579         int y= ui_menu_y(block) - MENU_ITEM_HEIGHT;
2580
2581         prop= RNA_struct_find_property(ptr, propname);
2582         if(prop) {
2583                 type= RNA_property_type(ptr, prop);
2584
2585                 if(type == PROP_BOOLEAN) {
2586                         if(RNA_property_boolean_get(ptr, prop))
2587                                 icon= ICON_CHECKBOX_HLT;
2588
2589                         return uiDefIconTextButR(block, TOG, 0, icon, name, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT-1, ptr, propname, 0, 0, 0, 0, 0, NULL);
2590                 }
2591                 else if(type == PROP_ENUM) {
2592                         RNA_property_enum_items(ptr, prop, &item, &totitem);
2593
2594                         value= 0;
2595                         for(a=0; a<totitem; a++) {
2596                                 if(propvalue && strcmp(propvalue, item[a].identifier) == 0) {
2597                                         value= item[a].value;
2598                                         if(!name)
2599                                                 name= (char*)item[a].name;
2600
2601                                         if(RNA_property_enum_get(ptr, prop) == value)
2602                                                 icon= ICON_CHECKBOX_HLT;
2603                                         break;
2604                                 }
2605                         }
2606
2607                         if(a != totitem)
2608                                 return uiDefIconTextButR(block, ROW, 0, icon, name, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT-1, ptr, propname, 0, 0, value, 0, 0, NULL);
2609                 }
2610         }
2611
2612         /* not found */
2613         uiBlockSetButLock(block, 1, "");
2614         but= uiDefIconTextBut(block, BUT, 0, ICON_BLANK1, propname, 0, y, MENU_WIDTH, MENU_ITEM_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
2615         uiBlockClearButLock(block);
2616
2617         return but;
2618
2619
2620 /* END Button containing both string label and icon */
2621
2622 void uiAutoBlock(uiBlock *block, float minx, float miny, float sizex, float sizey, int flag)
2623 {
2624         block->minx= minx;
2625         block->maxx= minx+sizex;
2626         block->miny= miny;
2627         block->maxy= miny+sizey;
2628         
2629         block->autofill= flag;  /* also check for if it has to be done */
2630
2631 }
2632
2633 void uiSetButLink(uiBut *but, void **poin, void ***ppoin, short *tot, int from, int to)
2634 {
2635         uiLink *link;
2636         
2637         link= but->link= MEM_callocN(sizeof(uiLink), "new uilink");
2638         
2639         link->poin= poin;
2640         link->ppoin= ppoin;
2641         link->totlink= tot;
2642         link->fromcode= from;
2643         link->tocode= to;
2644 }
2645
2646 /* cruft to make uiBlock and uiBut private */
2647
2648 int uiBlocksGetYMin(ListBase *lb)
2649 {
2650         uiBlock *block;
2651         int min= 0;
2652         
2653         for (block= lb->first; block; block= block->next)
2654                 if (block==lb->first || block->miny<min)
2655                         min= block->miny;
2656                         
2657         return min;
2658 }
2659
2660 int uiBlockGetCol(uiBlock *block)
2661 {
2662         return block->themecol;
2663 }
2664 void uiBlockSetCol(uiBlock *block, int col)
2665 {
2666         block->themecol= col;
2667 }
2668 void uiBlockSetEmboss(uiBlock *block, int emboss)
2669 {
2670         block->dt= emboss;
2671 }
2672 void uiBlockSetDirection(uiBlock *block, int direction)
2673 {
2674         block->direction= direction;
2675 }
2676
2677 /* this call escapes if there's alignment flags */
2678 void uiBlockFlipOrder(uiBlock *block)
2679 {
2680         ListBase lb;
2681         uiBut *but, *next;
2682         float centy, miny=10000, maxy= -10000;
2683
2684 //      if(U.uiflag & USER_PLAINMENUS)
2685 //              return;
2686         
2687         for(but= block->buttons.first; but; but= but->next) {
2688                 if(but->flag & UI_BUT_ALIGN) return;
2689                 if(but->y1 < miny) miny= but->y1;
2690                 if(but->y2 > maxy) maxy= but->y2;
2691         }
2692         /* mirror trick */
2693         centy= (miny+maxy)/2.0;
2694         for(but= block->buttons.first; but; but= but->next) {
2695                 but->y1 = centy-(but->y1-centy);
2696                 but->y2 = centy-(but->y2-centy);
2697                 SWAP(float, but->y1, but->y2);
2698         }
2699         
2700         /* also flip order in block itself, for example for arrowkey */
2701         lb.first= lb.last= NULL;
2702         but= block->buttons.first;
2703         while(but) {
2704                 next= but->next;
2705                 BLI_remlink(&block->buttons, but);
2706                 BLI_addtail(&lb, but);
2707                 but= next;
2708         }
2709         block->buttons= lb;
2710 }
2711
2712
2713 void uiBlockSetFlag(uiBlock *block, int flag)
2714 {
2715         block->flag= flag;
2716 }
2717 void uiBlockSetXOfs(uiBlock *block, int xofs)
2718 {
2719         block->xofs= xofs;
2720 }
2721 void* uiBlockGetCurFont(uiBlock *block)
2722 {
2723         return block->curfont;
2724 }
2725
2726 void uiButSetFlag(uiBut *but, int flag)
2727 {
2728         but->flag|= flag;
2729 }
2730 void uiButClearFlag(uiBut *but, int flag)
2731 {
2732         but->flag&= ~flag;
2733 }
2734
2735 int uiButGetRetVal(uiBut *but)
2736 {
2737         return but->retval;
2738 }
2739
2740 PointerRNA *uiButGetOperatorPtrRNA(uiBut *but)
2741 {
2742         if(but->opname && !but->opptr) {
2743                 but->opptr= MEM_callocN(sizeof(PointerRNA), "uiButOpPtr");
2744                 WM_operator_properties_create(but->opptr, but->opname);
2745         }
2746
2747         return but->opptr;
2748 }
2749
2750 void uiBlockSetHandleFunc(uiBlock *block, void (*func)(struct bContext *C, void *arg, int event), void *arg)
2751 {
2752         block->handle_func= func;
2753         block->handle_func_arg= arg;
2754 }
2755
2756 void uiBlockSetButmFunc(uiBlock *block, void (*func)(struct bContext *C, void *arg, int but_a2), void *arg)
2757 {
2758         block->butm_func= func;
2759         block->butm_func_arg= arg;
2760 }
2761
2762 void uiBlockSetFunc(uiBlock *block, void (*func)(struct bContext *C, void *arg1, void *arg2), void *arg1, void *arg2)
2763 {
2764         block->func= func;
2765         block->func_arg1= arg1;
2766         block->func_arg2= arg2;
2767 }
2768
2769 void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)())
2770 {
2771         block->drawextra= func;
2772 }
2773
2774 void uiButSetFunc(uiBut *but, void (*func)(struct bContext *C, void *arg1, void *arg2), void *arg1, void *arg2)
2775 {
2776         but->func= func;
2777         but->func_arg1= arg1;
2778         but->func_arg2= arg2;
2779 }
2780
2781 void uiButSetCompleteFunc(uiBut *but, void (*func)(struct bContext *C, char *str, void *arg), void *arg)
2782 {
2783         but->autocomplete_func= func;
2784         but->autofunc_arg= arg;
2785 }
2786
2787 uiBut *uiDefIDPoinBut(uiBlock *block, uiIDPoinFuncFP func, short blocktype, int retval, char *str, short x1, short y1, short x2, short y2, void *idpp, char *tip)
2788 {
2789         uiBut *but= ui_def_but(block, IDPOIN, retval, str, x1, y1, x2, y2, NULL, 0.0, 0.0, 0.0, 0.0, tip);
2790         but->idpoin_func= func;
2791         but->idpoin_idpp= (ID**) idpp;
2792         ui_check_but(but);
2793         
2794         if(blocktype)
2795                 uiButSetCompleteFunc(but, autocomplete_id, (void *)(intptr_t)blocktype);
2796
2797         return but;
2798 }
2799
2800 uiBut *uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
2801 {
2802         uiBut *but= ui_def_but(block, BLOCK, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
2803         but->block_func= func;
2804         ui_check_but(but);
2805         return but;
2806 }
2807
2808 uiBut *uiDefPulldownBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
2809 {
2810         uiBut *but= ui_def_but(block, PULLDOWN, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
2811         but->block_func= func;
2812         ui_check_but(but);
2813         return but;
2814 }
2815
2816 /* Block button containing both string label and icon */
2817 uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip)
2818 {
2819         uiBut *but= ui_def_but(block, BLOCK, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
2820         
2821         but->icon= (BIFIconID) icon;
2822         but->flag|= UI_HAS_ICON;
2823
2824         but->flag|= UI_ICON_LEFT;
2825         but->flag|= UI_ICON_RIGHT;
2826
2827         but->block_func= func;
2828         ui_check_but(but);
2829         
2830         return but;
2831 }
2832
2833 /* Block button containing icon */
2834 uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int retval, int icon, short x1, short y1, short x2, short y2, char *tip)
2835 {
2836         uiBut *but= ui_def_but(block, BLOCK, retval, "", x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
2837         
2838         but->icon= (BIFIconID) icon;
2839         but->flag|= UI_HAS_ICON;
2840         
2841         but->flag|= UI_ICON_LEFT;
2842         but->flag|= UI_ICON_RIGHT;
2843         
2844         but->block_func= func;
2845         ui_check_but(but);
2846         
2847         return but;
2848 }
2849
2850 void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip)
2851 {
2852         uiBut *but= ui_def_but(block, KEYEVT|SHO, retval, str, x1, y1, x2, y2, spoin, 0.0, 0.0, 0.0, 0.0, tip);
2853         ui_check_but(but);
2854 }
2855
2856 /* Program Init/Exit */
2857
2858 void UI_init(void)
2859 {
2860         uiDefFont(UI_HELVB,
2861                                 BMF_GetFont(BMF_kHelveticaBold14),
2862                                 BMF_GetFont(BMF_kHelveticaBold12),
2863                                 BMF_GetFont(BMF_kHelveticaBold10),
2864                                 BMF_GetFont(BMF_kHelveticaBold8));
2865         uiDefFont(UI_HELV,
2866                                 BMF_GetFont(BMF_kHelvetica12),
2867                                 BMF_GetFont(BMF_kHelvetica12),
2868                                 BMF_GetFont(BMF_kHelvetica10),
2869                                 BMF_GetFont(BMF_kHelveticaBold8));
2870
2871         ui_resources_init();
2872 }
2873
2874 void UI_init_userdef()
2875 {
2876         ui_text_init_userdef();
2877         ui_theme_init_userdef();
2878 }
2879
2880 void UI_exit(void)
2881 {
2882         ui_resources_free();
2883 }
2884