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