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