- pulldowns and 'BLOCK' buttons now open automatic, when mouseover
[blender.git] / source / blender / src / interface.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 /* 
34      a full doc with API notes can be found in bf-blender/blender/doc/interface_API.txt
35
36  */
37  
38
39 #include <math.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46
47 #ifndef WIN32
48 #include <unistd.h>
49 #else
50 #include <io.h>
51 #include "BLI_winstuff.h"
52 #endif   
53
54 #include "MEM_guardedalloc.h"
55
56 #include "PIL_time.h"
57
58 #include "BMF_Api.h"
59 #include "BIF_language.h"
60 #ifdef INTERNATIONAL
61 #include "FTF_Api.h"
62 #endif // INTERNATIONAL
63
64 #include "BLI_blenlib.h"
65 #include "BLI_arithb.h"
66 #include "BLI_editVert.h"
67
68 #include "DNA_screen_types.h"
69 #include "DNA_space_types.h"
70 #include "DNA_userdef_types.h"
71 #include "DNA_vec_types.h"
72
73 #include "BKE_blender.h"
74 #include "BKE_utildefines.h"
75 #include "BKE_global.h"
76
77 #include "BIF_gl.h"
78 #include "BIF_graphics.h"
79 #include "BIF_keyval.h"
80 #include "BIF_mainqueue.h"
81 #include "BIF_resources.h"
82 #include "BIF_screen.h"
83 #include "BIF_toolbox.h"
84 #include "BIF_mywindow.h"
85 #include "BIF_space.h"
86 #include "BIF_glutil.h"
87 #include "BIF_interface.h"
88 #include "BIF_butspace.h"
89
90 #include "BSE_view.h"
91
92 #include "mydevice.h"
93 #include "interface.h"
94 #include "blendef.h"
95
96 /* naming conventions:
97  * 
98  * uiBlahBlah()         external function
99  * ui_blah_blah()       internal function
100  */
101
102 /***/
103
104 typedef struct {
105         short xim, yim;
106         unsigned int *rect;
107         short xofs, yofs;
108 } uiIconImage;
109
110 typedef struct {
111         short mval[2];
112         short qual, val;
113         int event;
114 } uiEvent;
115
116 typedef struct {
117         void *xl, *large, *medium, *small;
118 } uiFont;
119
120 typedef struct uiLinkLine uiLinkLine;
121 struct uiLinkLine {                             /* only for draw/edit */
122         uiLinkLine *next, *prev;
123
124         short flag, pad;
125         
126         uiBut *from, *to;       
127 };
128
129 typedef struct {
130         void **poin;            /* pointer to original pointer */
131         void ***ppoin;          /* pointer to original pointer-array */
132         short *totlink;         /* if pointer-array, here is the total */
133         
134         short maxlink, pad;
135         short fromcode, tocode;
136         
137         ListBase lines;
138 } uiLink;
139
140 struct uiBut {
141         uiBut *next, *prev;
142         short type, pointype, bit, bitnr, retval, flag, strwidth, ofs, pos;
143
144         char *str;
145         char strdata[UI_MAX_NAME_STR];
146         char drawstr[UI_MAX_DRAW_STR];
147         
148         float x1, y1, x2, y2;
149
150         char *poin;
151         float min, max;
152         float a1, a2, rt[4];
153         float aspect;
154
155         void (*func)(void *, void *);
156         void *func_arg1;
157         void *func_arg2;
158
159         void (*embossfunc)(BIFColorID, float, float, float, float, float, int);
160
161         uiLink *link;
162         
163         char *tip, *lockstr;
164
165         BIFColorID col;
166         void *font;
167
168         BIFIconID icon;
169         short lock, win;
170         short iconadd;
171
172                 /* IDPOIN data */
173         uiIDPoinFuncFP idpoin_func;
174         ID **idpoin_idpp;
175
176                 /* BLOCK data */
177         uiBlockFuncFP block_func;
178
179                 /* BUTM data */
180         void (*butm_func)(void *arg, int event);
181         void *butm_func_arg;
182         
183                 /* pointer back */
184         uiBlock *block;
185 };
186
187 struct uiBlock {
188         uiBlock *next, *prev;
189         
190         ListBase buttons;
191         Panel *panel;
192         
193         char name[UI_MAX_NAME_STR];
194         
195         float winmat[4][4];
196         
197         float minx, miny, maxx, maxy;
198         float aspect;
199
200         void (*butm_func)(void *arg, int event);
201         void *butm_func_arg;
202
203         void (*func)(void *arg1, void *arg2);
204         void *func_arg1;
205         void *func_arg2;
206         
207         BIFColorID col;
208         short font;     /* indices */
209         int afterval;
210         void *curfont;
211         
212         short autofill, flag, win, winq, direction, dt, frontbuf;  //frontbuf see below
213         void *saveunder;
214         
215         float xofs, yofs;       // offset to parent button
216         rctf parentrct;         // for pulldowns, rect the mouse is allowed outside of menu (parent button)
217 };
218
219 /* block->frontbuf: (only internal here), to nice localize the old global var uiFrontBuf */
220 #define UI_NEED_DRAW_FRONT              1
221 #define UI_HAS_DRAW_FRONT               2
222
223 /* panel drawing defines */
224 #define PNL_GRID        4
225 #define PNL_DIST        8
226 #define PNL_SAFETY      8
227 #define PNL_HEADER  20
228
229 /* ************ GLOBALS ************* */
230
231 static float UIwinmat[4][4];
232 static int UIlock= 0, UIafterval;
233 static char *UIlockstr=NULL;
234 static void (*UIafterfunc)(void *arg, int event);
235 static void *UIafterfunc_arg;
236
237 static uiFont UIfont[UI_ARRAY];  // no init needed
238 static uiBut *UIbuttip;
239
240 /* ************* PROTOTYPES ***************** */
241
242 static void ui_check_but(uiBut *but);
243 static void ui_set_but_val(uiBut *but, double value);
244 static double ui_get_but_val(uiBut *but);
245
246 static void ui_draw_panel(uiBlock *block);
247 static void ui_panel_push(uiBlock *block);
248 static void ui_panel_pop(uiBlock *block);
249 static void ui_drag_panel(uiBlock *block);
250 static void ui_do_panel(uiBlock *block, uiEvent *uevent);
251 static int panel_has_tabs(Panel *panel);
252
253 /* ****************************** */
254
255 static int uibut_contains_pt(uiBut *but, short *pt)
256 {
257         return ((but->x1<pt[0] && but->x2>=pt[0]) && 
258                         (but->y1<pt[1] && but->y2>=pt[1]));
259 }
260
261 static void uibut_do_func(uiBut *but)
262 {
263         if (but->func) {
264                 but->func(but->func_arg1, but->func_arg2);
265         }
266 }
267
268 /* ************* SAVE UNDER ************ */
269
270 typedef struct {
271         short x, y, sx, sy, oldwin;
272         int oldcursor;
273         unsigned int *rect;
274 } uiSaveUnder;
275
276
277 static void ui_paste_under(uiSaveUnder *su)
278 {
279         
280         if(su) {
281                 glDisable(GL_DITHER);
282                 glRasterPos2f( su->x-0.5,  su->y-0.5 );
283                 glDrawPixels(su->sx, su->sy, GL_RGBA, GL_UNSIGNED_BYTE, su->rect);
284                 glEnable(GL_DITHER);
285
286                 if(su->oldwin) {
287                         mywinset(su->oldwin);
288                         if (su->oldcursor) {
289                                 set_cursor(su->oldcursor);
290                         }
291                 }
292                 
293                 MEM_freeN(su->rect);
294                 MEM_freeN(su);
295         }
296 }
297
298
299 static uiSaveUnder *ui_save_under(int x, int y, int sx, int sy)
300 {
301         uiSaveUnder *su=NULL;
302         
303         if(sx>1 && sy>1) {
304                 
305                 su= MEM_callocN(sizeof(uiSaveUnder), "save under");     
306                 
307                 su->rect= MEM_mallocN(sx*sy*4, "temp_frontbuffer_image");
308                 su->x= x;
309                 su->y= y;
310                 su->sx= sx;
311                 su->sy= sy;
312                 glReadPixels(x, y, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, su->rect);
313         }
314         
315         return su;
316 }
317
318
319
320
321
322 /* ************* DRAW ************** */
323
324
325 static void ui_graphics_to_window(int win, float *x, float *y)  /* for rectwrite  */
326 {
327         float gx, gy;
328         int sx, sy;
329         int getsizex, getsizey;
330
331         bwin_getsize(win, &getsizex, &getsizey);
332         bwin_getsuborigin(win, &sx, &sy);
333
334         gx= *x;
335         gy= *y;
336         *x= sx + getsizex*(0.5+ 0.5*(gx*UIwinmat[0][0]+ gy*UIwinmat[1][0]+ UIwinmat[3][0]));
337         *y= sy + getsizey*(0.5+ 0.5*(gx*UIwinmat[0][1]+ gy*UIwinmat[1][1]+ UIwinmat[3][1]));
338 }
339
340
341
342 static void ui_window_to_graphics(int win, float *x, float *y)  /* for mouse cursor */
343 {
344         float a, b, c, d, e, f, px, py;
345         int getsizex, getsizey;
346                 
347         bwin_getsize(win, &getsizex, &getsizey);
348
349         a= .5*getsizex*UIwinmat[0][0];
350         b= .5*getsizex*UIwinmat[1][0];
351         c= .5*getsizex*(1.0+UIwinmat[3][0]);
352
353         d= .5*getsizey*UIwinmat[0][1];
354         e= .5*getsizey*UIwinmat[1][1];
355         f= .5*getsizey*(1.0+UIwinmat[3][1]);
356         
357         px= *x;
358         py= *y;
359         
360         *y=  (a*(py-f) + d*(c-px))/(a*e-d*b);
361         *x= (px- b*(*y)- c)/a;
362         
363 }
364
365 static uiSaveUnder *ui_bgnpupdraw(int startx, int starty, int endx, int endy, int cursor)
366 {
367         uiSaveUnder *su;
368         short oldwin;
369         
370         #if defined(__sgi) || defined(__sun)
371         /* this is a dirty patch: gets sometimes the backbuffer */
372         my_get_frontbuffer_image(0, 0, 1, 1);
373         my_put_frontbuffer_image();
374         #endif
375
376         oldwin= mywinget();
377
378         mywinset(G.curscreen->mainwin);
379         
380         /* tinsy bit larger, 1 pixel on the edge */
381         
382         glReadBuffer(GL_FRONT);
383         glDrawBuffer(GL_FRONT);
384         
385         /* for geforce and other cards */
386         glFinish();
387
388         su= ui_save_under(startx-1, starty-1, endx-startx+2, endy-starty+6);
389         if(su) su->oldwin= oldwin;
390         
391         if(su && cursor) {
392                 su->oldcursor= get_cursor();
393                 set_cursor(CURSOR_STD);
394         }
395         
396         return su;
397 }
398
399 static void ui_endpupdraw(uiSaveUnder *su)
400 {
401
402         /* for geforce and other cards */
403
404         glReadBuffer(GL_FRONT);
405         glDrawBuffer(GL_FRONT);
406         
407         glFinish();
408
409         if(su) {
410                 ui_paste_under(su);
411         }
412         glReadBuffer(GL_BACK);
413         glDrawBuffer(GL_BACK);
414 }
415
416
417 static void ui_draw_icon(uiBut *but, BIFIconID icon)
418 {
419         float xs=0, ys=0;
420         
421         /* check for aligned icons (in case of IconTextBut) */
422         if (but->type == ICONTEXTROW) {
423                 xs= (but->x1+but->x2- BIF_get_icon_width(icon))/2.0;
424                 ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
425         }
426         else {
427                 if(but->flag & UI_ICON_LEFT) {
428                         if (but->type==BUTM) {
429                                 xs= but->x1+1.0;
430                         }
431                         else {
432                                 xs= but->x1+6.0;
433                         }
434                         ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
435                 }
436                 if(but->flag & UI_ICON_RIGHT) {
437                         xs= but->x2-17.0;
438                         ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
439                 }
440                 if (!((but->flag & UI_ICON_RIGHT) || (but->flag & UI_ICON_LEFT))) {
441                         xs= (but->x1+but->x2- BIF_get_icon_width(icon))/2.0;
442                         ys= (but->y1+but->y2- BIF_get_icon_height(icon))/2.0;
443                 }
444         }
445         /* END check for aligned icons (in case of IconTextBut) */
446
447         glRasterPos2f(xs, ys);
448
449         if(but->aspect>1.1) glPixelZoom(1.0/but->aspect, 1.0/but->aspect);
450
451         glEnable(GL_BLEND);
452         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
453
454         if(but->flag & UI_SELECT) {
455                 if(but->flag & UI_ACTIVE) {
456                         BIF_draw_icon_blended(icon, but->col, COLORSHADE_DARK);
457                 } else {
458                         BIF_draw_icon_blended(icon, but->col, COLORSHADE_GREY);
459                 }
460         }
461         else {
462                 if ((but->flag & UI_ACTIVE) && but->type==BUTM) {
463                         BIF_draw_icon_blended(icon, BUTMACTIVE, COLORSHADE_MEDIUM);
464                 } else if (but->flag & UI_ACTIVE) {
465                         BIF_draw_icon_blended(icon, but->col, COLORSHADE_HILITE);
466                 } else {
467                         BIF_draw_icon_blended(icon, but->col, COLORSHADE_MEDIUM);
468                 }
469         }
470
471         glBlendFunc(GL_ONE, GL_ZERO);
472         glDisable(GL_BLEND);
473
474         glPixelZoom(1.0, 1.0);
475 }
476
477 /* not used
478 static void ui_draw_outlineX(float x1, float y1, float x2, float y2, float asp1)
479 {
480         float vec[2];
481         
482         glBegin(GL_LINE_LOOP);
483         vec[0]= x1+asp1; vec[1]= y1-asp1;
484         glVertex2fv(vec);
485         vec[0]= x2-asp1; 
486         glVertex2fv(vec);
487         vec[0]= x2+asp1; vec[1]= y1+asp1;
488         glVertex2fv(vec);
489         vec[1]= y2-asp1;
490         glVertex2fv(vec);
491         vec[0]= x2-asp1; vec[1]= y2+asp1;
492         glVertex2fv(vec);
493         vec[0]= x1+asp1;
494         glVertex2fv(vec);
495         vec[0]= x1-asp1; vec[1]= y2-asp1;
496         glVertex2fv(vec);
497         vec[1]= y1+asp1;
498         glVertex2fv(vec);
499         glEnd();                
500         
501 }
502
503 static void ui_emboss_R(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
504 {
505
506         if(flag & UI_SELECT) {
507                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_DARK);
508                 else BIF_set_color(bc, COLORSHADE_GREY);
509         }
510         else {
511                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_HILITE);
512                 else BIF_set_color(bc, COLORSHADE_MEDIUM);
513         }
514         
515         uiSetRoundBox(15);
516         uiRoundBox(x1, y1, x2, y2, 6);
517         cpack(0x0);
518         uiSetRoundBox(16+15);
519         uiRoundRect(x1, y1, x2, y2, 6);
520         uiSetRoundBox(15);
521 }
522
523 */
524
525
526 static void ui_emboss_X(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
527 {
528
529         float asp1;
530         
531         asp1= asp;
532
533         /*x1+= asp1;*/
534         x2-= asp1;      
535         /*y1+= asp1;*/
536         y2-= asp1;
537
538         /* SHADED BUTTON */
539         glShadeModel(GL_SMOOTH);
540         glBegin(GL_QUADS);
541         
542
543         if(flag & UI_SELECT) {
544                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LGREY);
545                 else BIF_set_color(bc, COLORSHADE_LGREY);
546         }
547         else {
548                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_HILITE);
549                 else BIF_set_color(bc, COLORSHADE_HILITE);
550         }
551
552         glVertex2f(x1,y1);
553         glVertex2f(x2,y1);
554
555         if(flag & UI_SELECT) {
556                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
557                 else BIF_set_color(bc, COLORSHADE_GREY);
558         }
559         else {
560                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LIGHT);
561                 BIF_set_color(bc, COLORSHADE_LIGHT);
562         }
563
564         glVertex2f(x2,(y2-(y2-y1)/3));
565         glVertex2f(x1,(y2-(y2-y1)/3));
566         glEnd();
567         
568
569         glShadeModel(GL_FLAT);
570         glBegin(GL_QUADS);
571         
572         if(flag & UI_SELECT) {
573                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
574                 else BIF_set_color(bc, COLORSHADE_GREY);
575         }
576         else {
577                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LIGHT);
578                 BIF_set_color(bc, COLORSHADE_LIGHT);
579         }
580
581         glVertex2f(x1,(y2-(y2-y1)/3));
582         glVertex2f(x2,(y2-(y2-y1)/3));
583         glVertex2f(x2,y2);
584         glVertex2f(x1,y2);
585
586         glEnd();
587         /* END SHADED BUTTON */
588
589         /* OUTER SUNKEN EFFECT */
590         /* left */
591         glShadeModel(GL_SMOOTH);
592         glBegin(GL_LINES);
593         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
594         glVertex2f(x1-1,y1);
595         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
596         glVertex2f(x1-1,y2);
597         glEnd();
598         
599         /* right */
600         glShadeModel(GL_SMOOTH);
601         glBegin(GL_LINES);
602         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
603         glVertex2f(x2+1,y1);
604         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
605         glVertex2f(x2+1,y2);
606         glEnd();
607
608         /* bottom */
609         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
610         fdrawline(x1, y1-1, x2, y1-1);
611         /* END OUTER SUNKEN EFFECT */
612         
613         /* INNER OUTLINE */
614         glShadeModel(GL_FLAT);
615         
616         /* top */
617         if(flag & UI_SELECT) {
618                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
619                 else BIF_set_color(bc, COLORSHADE_GREY);
620         }
621         else {
622                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_WHITE);
623                 BIF_set_color(bc, COLORSHADE_WHITE);
624         }
625
626         fdrawline(x1, (y2-1), x2, y2-1);
627         
628         /* bottom */
629         
630         if(flag & UI_SELECT) {
631                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LGREY);
632                 else BIF_set_color(bc, COLORSHADE_LGREY);
633         }
634         else {
635                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LMEDIUM);
636                 BIF_set_color(bc, COLORSHADE_LMEDIUM);
637         }
638         fdrawline(x1, (y1+1), x2, y1+1);
639
640         /* left */
641         if(!(flag & UI_SELECT)) {
642                                         
643         glShadeModel(GL_SMOOTH);
644         glBegin(GL_LINES);
645         BIF_set_color(bc, COLORSHADE_WHITE);
646         glVertex2f(x1+1,y1+2);
647         BIF_set_color(bc, COLORSHADE_LGREY);
648         glVertex2f(x1+1,y2);
649         glEnd();
650         
651         }
652         
653         /* right */
654         if(!(flag & UI_SELECT)) {
655
656         glShadeModel(GL_SMOOTH);
657         glBegin(GL_LINES);
658         BIF_set_color(bc, COLORSHADE_LGREY);
659         glVertex2f(x2-1,y1+2);
660         BIF_set_color(bc, COLORSHADE_WHITE);
661         glVertex2f(x2-1,y2);
662         glEnd();
663         
664         }
665         /* END INNER OUTLINE */
666         
667         /* OUTER OUTLINE */
668         glShadeModel(GL_FLAT);
669         
670         /* underneath semi-fake-AA */
671         BIF_set_color(BUTGREY, COLORSHADE_GREY);
672         fdrawline(x1, y2, x2, y2);
673         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
674         fdrawline(x1, y1, x2, y1);
675
676         /* top */
677         BIF_set_color(BUTGREY, COLORSHADE_DARK);
678         fdrawline(x1+1, y2, x2, y2);
679
680         /* left */
681         fdrawline(x1, y1+1, x1, y2);
682
683         /* right */
684         fdrawline(x2, y1+1, x2, y2);
685         
686         /* bottom */
687         BIF_set_color(BUTGREY, COLORSHADE_DARK);
688         fdrawline(x1+1, y1, x2, y1);
689         /* END OUTER OUTLINE */
690         
691 }
692
693 static void ui_emboss_TEX(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
694 {
695
696         float asp1;
697         
698         asp1= asp;
699
700         /*x1+= asp1;*/
701         x2-= asp1;      
702         /*y1+= asp1;*/
703         y2-= asp1;
704
705         /* FLAT TEXT/NUM FIELD */
706         glShadeModel(GL_FLAT);
707         glBegin(GL_QUADS);
708
709         if(flag & UI_SELECT) {
710                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LGREY);
711                 else BIF_set_color(bc, COLORSHADE_LGREY);
712         }
713         else {
714                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LMEDIUM);
715                 else BIF_set_color(bc, COLORSHADE_LMEDIUM);
716         }
717
718         glVertex2f(x1,y1);
719         glVertex2f(x2,y1);
720         glVertex2f(x2,y2);
721         glVertex2f(x1,y2);
722
723         glEnd();
724         /* END FLAT TEXT/NUM FIELD */
725         
726         /* OUTER SUNKEN EFFECT */
727         /* left */
728         glShadeModel(GL_SMOOTH);
729         glBegin(GL_LINES);
730         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
731         glVertex2f(x1-1,y1);
732         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
733         glVertex2f(x1-1,y2);
734         glEnd();
735         
736         /* right */
737         glShadeModel(GL_SMOOTH);
738         glBegin(GL_LINES);
739         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
740         glVertex2f(x2+1,y1);
741         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
742         glVertex2f(x2+1,y2);
743         glEnd();
744
745         /* bottom */
746         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
747         fdrawline(x1, y1-1, x2, y1-1);
748         /* END OUTER SUNKEN EFFECT */
749
750         /* OUTER OUTLINE */
751         glShadeModel(GL_FLAT);
752         
753         /* underneath semi-fake-AA */
754         BIF_set_color(BUTGREY, COLORSHADE_GREY);
755         fdrawline(x1, y2, x2, y2);
756         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
757         fdrawline(x1, y1, x2, y1);
758
759         /* top */
760         BIF_set_color(BUTGREY, COLORSHADE_DARK);
761         fdrawline(x1+1, y2, x2, y2);
762
763         /* left */
764         fdrawline(x1, y1+1, x1, y2);
765
766         /* right */
767         fdrawline(x2, y1+1, x2, y2);
768         
769         /* bottom */
770         BIF_set_color(BUTGREY, COLORSHADE_DARK);
771         fdrawline(x1+1, y1, x2, y1);
772         /* END OUTER OUTLINE */
773 }
774
775 static void ui_emboss_NUM(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
776 {
777
778         float asp1;
779
780         asp1= asp;
781
782         /*x1+= asp1;*/
783         x2-= asp1;      
784         /*y1+= asp1;*/
785         y2-= asp1;
786
787         /* FLAT TEXT/NUM FIELD */
788         glShadeModel(GL_FLAT);
789         glBegin(GL_QUADS);
790
791         if(flag & UI_SELECT) {
792                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LGREY);
793                 else BIF_set_color(bc, COLORSHADE_LGREY);
794         }
795         else {
796                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LMEDIUM);
797                 else BIF_set_color(bc, COLORSHADE_LMEDIUM);
798         }
799
800         glVertex2f(x1,y1);
801         glVertex2f(x2,y1);
802         glVertex2f(x2,y2);
803         glVertex2f(x1,y2);
804
805         glEnd();
806         /* END FLAT TEXT/NUM FIELD */
807         
808         /* OUTER SUNKEN EFFECT */
809         /* left */
810         glShadeModel(GL_SMOOTH);
811         glBegin(GL_LINES);
812         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
813         glVertex2f(x1-1,y1);
814         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
815         glVertex2f(x1-1,y2);
816         glEnd();
817         
818         /* right */
819         glShadeModel(GL_SMOOTH);
820         glBegin(GL_LINES);
821         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
822         glVertex2f(x2+1,y1);
823         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
824         glVertex2f(x2+1,y2);
825         glEnd();
826
827         /* bottom */
828         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
829         fdrawline(x1, y1-1, x2, y1-1);
830         /* END OUTER SUNKEN EFFECT */
831
832         /* OUTER OUTLINE */
833         glShadeModel(GL_FLAT);
834         
835         /* underneath semi-fake-AA */
836         BIF_set_color(BUTGREY, COLORSHADE_GREY);
837         fdrawline(x1, y2, x2, y2);
838         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
839         fdrawline(x1, y1, x2, y1);
840
841         /* top */
842         BIF_set_color(BUTGREY, COLORSHADE_DARK);
843         fdrawline(x1+1, y2, x2, y2);
844
845         /* left */
846         fdrawline(x1, y1+1, x1, y2);
847
848         /* right */
849         fdrawline(x2, y1+1, x2, y2);
850         
851         /* bottom */
852         BIF_set_color(BUTGREY, COLORSHADE_DARK);
853         fdrawline(x1+1, y1, x2, y1);
854         /* END OUTER OUTLINE */
855
856         /* SIDE ARROWS */
857         /* left */
858         glShadeModel(GL_FLAT);
859         glBegin(GL_TRIANGLES);
860         
861         if(flag & UI_SELECT) {
862                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_DARK);
863                 else BIF_set_color(bc, COLORSHADE_DARK);
864         }
865         else {
866                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
867                 else BIF_set_color(bc, COLORSHADE_LGREY);
868         }
869
870         glVertex2f((short)x1+5,(short)(y2-(y2-y1)/2));
871         glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)+4);
872         glVertex2f((short)x1+10,(short)(y2-(y2-y1)/2)-4);
873         glEnd();
874
875         /* right */
876         glShadeModel(GL_FLAT);
877         glBegin(GL_TRIANGLES);
878
879         if(flag & UI_SELECT) {
880                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_DARK);
881                 else BIF_set_color(bc, COLORSHADE_DARK);
882         }
883         else {
884                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
885                 else BIF_set_color(bc, COLORSHADE_LGREY);
886         }
887
888         glVertex2f((short)x2-5,(short)(y2-(y2-y1)/2));
889         glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)-4);
890         glVertex2f((short)x2-10,(short)(y2-(y2-y1)/2)+4);
891         glEnd();
892         /* END SIDE ARROWS */
893
894 }
895
896 static void ui_emboss_MENU(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
897 {
898
899         float asp1;
900         
901         asp1= asp;
902
903         /*x1+= asp1;*/
904         x2-= asp1;      
905         /*y1+= asp1;*/
906         y2-= asp1;
907
908         /* SHADED BUTTON */
909         glShadeModel(GL_SMOOTH);
910         glBegin(GL_QUADS);
911         
912
913         if(flag & UI_SELECT) {
914                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LGREY);
915                 else BIF_set_color(bc, COLORSHADE_LGREY);
916         }
917         else {
918                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_HILITE);
919                 else BIF_set_color(bc, COLORSHADE_HILITE);
920         }
921
922         glVertex2f(x1,y1);
923         glVertex2f(x2,y1);
924
925         if(flag & UI_SELECT) {
926                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
927                 else BIF_set_color(bc, COLORSHADE_GREY);
928         }
929         else {
930                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LIGHT);
931                 BIF_set_color(bc, COLORSHADE_LIGHT);
932         }
933
934         glVertex2f(x2,(y2-(y2-y1)/3));
935         glVertex2f(x1,(y2-(y2-y1)/3));
936         glEnd();
937         
938
939         glShadeModel(GL_FLAT);
940         glBegin(GL_QUADS);
941         
942         if(flag & UI_SELECT) {
943                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
944                 else BIF_set_color(bc, COLORSHADE_GREY);
945         }
946         else {
947                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LIGHT);
948                 BIF_set_color(bc, COLORSHADE_LIGHT);
949         }
950
951         glVertex2f(x1,(y2-(y2-y1)/3));
952         glVertex2f(x2,(y2-(y2-y1)/3));
953         glVertex2f(x2,y2);
954         glVertex2f(x1,y2);
955
956         glEnd();
957         /* END SHADED BUTTON */
958
959         /* OUTER SUNKEN EFFECT */
960         /* left */
961         glShadeModel(GL_SMOOTH);
962         glBegin(GL_LINES);
963         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
964         glVertex2f(x1-1,y1);
965         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
966         glVertex2f(x1-1,y2);
967         glEnd();
968         
969         /* right */
970         glShadeModel(GL_SMOOTH);
971         glBegin(GL_LINES);
972         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
973         glVertex2f(x2+1,y1);
974         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
975         glVertex2f(x2+1,y2);
976         glEnd();
977
978         /* bottom */
979         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
980         fdrawline(x1, y1-1, x2, y1-1);
981         /* END OUTER SUNKEN EFFECT */
982         
983         /* INNER OUTLINE */
984         glShadeModel(GL_FLAT);
985         
986         /* top */
987         if(flag & UI_SELECT) {
988                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
989                 else BIF_set_color(bc, COLORSHADE_GREY);
990         }
991         else {
992                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_WHITE);
993                 BIF_set_color(bc, COLORSHADE_WHITE);
994         }
995
996         fdrawline(x1, (y2-1), x2, y2-1);
997         
998         /* bottom */
999         
1000         if(flag & UI_SELECT) {
1001                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LGREY);
1002                 else BIF_set_color(bc, COLORSHADE_LGREY);
1003         }
1004         else {
1005                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LMEDIUM);
1006                 BIF_set_color(bc, COLORSHADE_LMEDIUM);
1007         }
1008         fdrawline(x1, (y1+1), x2, y1+1);
1009
1010         /* left */
1011         if(!(flag & UI_SELECT)) {
1012                                         
1013         glShadeModel(GL_SMOOTH);
1014         glBegin(GL_LINES);
1015         BIF_set_color(bc, COLORSHADE_WHITE);
1016         glVertex2f(x1+1,y1+2);
1017         BIF_set_color(bc, COLORSHADE_LGREY);
1018         glVertex2f(x1+1,y2);
1019         glEnd();
1020         
1021         }
1022         
1023         /* right */
1024         if(!(flag & UI_SELECT)) {
1025
1026         glShadeModel(GL_SMOOTH);
1027         glBegin(GL_LINES);
1028         BIF_set_color(bc, COLORSHADE_LGREY);
1029         glVertex2f(x2-1,y1+2);
1030         BIF_set_color(bc, COLORSHADE_WHITE);
1031         glVertex2f(x2-1,y2);
1032         glEnd();
1033         
1034         }
1035         /* END INNER OUTLINE */
1036         
1037         /* OUTER OUTLINE */
1038         glShadeModel(GL_FLAT);
1039         
1040         /* underneath semi-fake-AA */
1041         BIF_set_color(BUTGREY, COLORSHADE_GREY);
1042         fdrawline(x1, y2, x2, y2);
1043         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
1044         fdrawline(x1, y1, x2, y1);
1045
1046         /* top */
1047         BIF_set_color(BUTGREY, COLORSHADE_DARK);
1048         fdrawline(x1+1, y2, x2, y2);
1049
1050         /* left */
1051         fdrawline(x1, y1+1, x1, y2);
1052
1053         /* right */
1054         fdrawline(x2, y1+1, x2, y2);
1055         
1056         /* bottom */
1057         BIF_set_color(BUTGREY, COLORSHADE_DARK);
1058         fdrawline(x1+1, y1, x2, y1);
1059         /* END OUTER OUTLINE */
1060
1061         /* DARKENED AREA */
1062         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1063         glEnable(GL_BLEND);
1064         
1065         glColor4ub(0, 0, 0, 30);
1066         glRectf(x2-18, y1, x2, y2);
1067
1068         glDisable(GL_BLEND);
1069         /* END DARKENED AREA */
1070
1071         /* MENU DOUBLE-ARROW  */
1072         glShadeModel(GL_FLAT);
1073         glBegin(GL_TRIANGLES);
1074
1075         BIF_set_color(bc, COLORSHADE_DARK);
1076
1077         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+1);
1078         glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2)+1);
1079         glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2)+4);
1080         glEnd();
1081
1082         glBegin(GL_TRIANGLES);
1083
1084         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2));
1085         glVertex2f((short)x2-12,(short)(y2-(y2-y1)/2));
1086         glVertex2f((short)x2-8,(short)(y2-(y2-y1)/2)-3);
1087         glEnd();
1088         /* MENU DOUBLE-ARROW */
1089
1090 }
1091
1092 static void ui_emboss_TABL(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
1093 {
1094
1095         float asp1;
1096         
1097         asp1= asp;
1098
1099         /*x1+= asp1;*/
1100         x2-= asp1;      
1101         /*y1+= asp1;*/
1102         y2-= asp1;
1103
1104         glShadeModel(GL_SMOOTH);
1105         glBegin(GL_QUADS);
1106         
1107
1108         if(flag & UI_SELECT) {
1109                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_MEDIUM);
1110                 else BIF_set_color(bc, COLORSHADE_MEDIUM);
1111         }
1112         else {
1113                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_MEDIUM);
1114                 else BIF_set_color(bc, COLORSHADE_MEDIUM);
1115         }
1116
1117         
1118         //BIF_set_color(bc, COLORSHADE_MEDIUM);
1119
1120         glVertex2f(x1,y1);
1121         glVertex2f(x2,y1);
1122
1123         if(flag & UI_SELECT) {
1124                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
1125                 else BIF_set_color(bc, COLORSHADE_GREY);
1126         }
1127         else {
1128                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LIGHT);
1129                 BIF_set_color(bc, COLORSHADE_LIGHT);
1130         }
1131
1132
1133         //BIF_set_color(bc, COLORSHADE_LIGHT);
1134
1135         //glVertex2f(x2,(y1+(y2-y1)/2));
1136         glVertex2f(x2,(y2-(y2-y1)/3));
1137         glVertex2f(x1,(y2-(y2-y1)/3));
1138         glEnd();
1139         
1140
1141         glShadeModel(GL_FLAT);
1142         glBegin(GL_QUADS);
1143         
1144         if(flag & UI_SELECT) {
1145                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
1146                 else BIF_set_color(bc, COLORSHADE_GREY);
1147         }
1148         else {
1149                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_LIGHT);
1150                 BIF_set_color(bc, COLORSHADE_LIGHT);
1151         }
1152
1153         //BIF_set_color(bc, COLORSHADE_LIGHT);
1154
1155         glVertex2f(x1,(y2-(y2-y1)/3));
1156         glVertex2f(x2,(y2-(y2-y1)/3));
1157         glVertex2f(x2,y2);
1158         glVertex2f(x1,y2);
1159
1160         glEnd();
1161
1162
1163         /* inner outline */
1164         glShadeModel(GL_FLAT);
1165         
1166         /* top */
1167         
1168         if(flag & UI_SELECT) {
1169                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_GREY);
1170                 else BIF_set_color(bc, COLORSHADE_GREY);
1171         }
1172         else {
1173                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_WHITE);
1174                 BIF_set_color(bc, COLORSHADE_WHITE);
1175         }
1176
1177         fdrawline(x1, (y2-1), x2, y2-1);
1178
1179
1180         /* left */
1181         if(!(flag & UI_SELECT)) {
1182                                         
1183         glShadeModel(GL_SMOOTH);
1184         glBegin(GL_LINES);
1185         BIF_set_color(bc, COLORSHADE_WHITE);
1186         glVertex2f(x1+1,y1-1);
1187         BIF_set_color(bc, COLORSHADE_MEDIUM);
1188         glVertex2f(x1+1,y2);
1189         glEnd();
1190         
1191         }
1192         
1193         /* right */
1194         
1195         if(!(flag & UI_SELECT)) {
1196
1197         glShadeModel(GL_SMOOTH);
1198         glBegin(GL_LINES);
1199         BIF_set_color(bc, COLORSHADE_MEDIUM);
1200         glVertex2f(x2-1,y1+2);
1201         BIF_set_color(bc, COLORSHADE_WHITE);
1202         glVertex2f(x2-1,y2);
1203         glEnd();
1204         
1205         }
1206
1207         /* outer outline */
1208         glShadeModel(GL_FLAT);
1209         
1210         /* underneath semi-fake-AA */
1211         BIF_set_color(BUTGREY, COLORSHADE_GREY);
1212         fdrawline(x1, y2, x2, y2);
1213         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
1214         fdrawline(x1, y1, x2, y1);
1215
1216         /* top */
1217         BIF_set_color(BUTGREY, COLORSHADE_DARK);
1218         fdrawline(x1+1, y2, x2, y2);
1219
1220         /* left */
1221         fdrawline(x1, y1, x1, y2);
1222
1223         /* right */
1224         fdrawline(x2, y1, x2, y2);
1225
1226         /* outer sunken effect */
1227         /* left */
1228         glShadeModel(GL_SMOOTH);
1229         glBegin(GL_LINES);
1230         BIF_set_color(BUTGREY, COLORSHADE_LIGHT);
1231         glVertex2f(x1-1,y1);
1232         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
1233         glVertex2f(x1-1,y2);
1234         glEnd();
1235         
1236
1237
1238
1239 }
1240 static void ui_emboss_TABM(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
1241 {
1242 }
1243 static void ui_emboss_TABR(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
1244 {
1245 }
1246
1247
1248 void uiEmboss(float x1, float y1, float x2, float y2, int sel)
1249 {
1250         
1251         /* below */
1252         if(sel) glColor3ub(200,200,200);
1253         else glColor3ub(50,50,50);
1254         fdrawline(x1, y1, x2, y1);
1255
1256         /* right */
1257         fdrawline(x2, y1, x2, y2);
1258         
1259         /* top */
1260         if(sel) glColor3ub(50,50,50);
1261         else glColor3ub(200,200,200);
1262         fdrawline(x1, y2, x2, y2);
1263
1264         /* left */
1265         fdrawline(x1, y1, x1, y2);
1266         
1267 }
1268
1269 /* super minimal button as used in logic menu */
1270 static void ui_emboss_W(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
1271 {
1272         
1273         x1+= asp;
1274         x2-= asp;
1275         y1+= asp;
1276         y2-= asp;
1277
1278         /* paper */
1279         if(flag & UI_SELECT) {
1280                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_DARK);
1281                 else BIF_set_color(bc, COLORSHADE_GREY);
1282         }
1283         else {
1284                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_HILITE);
1285                 else BIF_set_color(bc, COLORSHADE_MEDIUM);
1286         }
1287         
1288         glRectf(x1, y1, x2, y2);
1289
1290         if(flag & UI_SELECT) {
1291                 BIF_set_color(bc, COLORSHADE_LIGHT);
1292                 
1293                 /* below */
1294                 fdrawline(x1, y1, x2, y1);
1295
1296                 /* right */
1297                 fdrawline(x2, y1, x2, y2);
1298         }
1299         else if(flag & UI_ACTIVE) {
1300                 BIF_set_color(bc, COLORSHADE_WHITE);
1301
1302                 /* top */
1303                 fdrawline(x1, y2, x2, y2);
1304         
1305                 /* left */
1306                 fdrawline(x1, y1, x1, y2);
1307         }
1308 }
1309
1310 /* minimal button with small black outline */
1311 static void ui_emboss_F(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
1312 {
1313         float asp1;
1314         
1315         /* paper */
1316         if(flag & UI_SELECT) {
1317                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_DARK);
1318                 else BIF_set_color(bc, COLORSHADE_GREY);
1319         }
1320         else {
1321                 if(flag & UI_ACTIVE) BIF_set_color(bc, COLORSHADE_HILITE);
1322                 else BIF_set_color(bc, COLORSHADE_MEDIUM);
1323         }
1324         
1325         glRectf(x1+1, y1+1, x2-1, y2-1);
1326
1327         asp1= asp;
1328
1329         x1+= asp1;
1330         x2-= asp1;
1331         y1+= asp1;
1332         y2-= asp1;
1333
1334         /* below */
1335         if(flag & UI_SELECT) BIF_set_color(bc, COLORSHADE_WHITE);
1336         else BIF_set_color(bc, COLORSHADE_DARK);
1337         fdrawline(x1, y1, x2, y1);
1338
1339         /* right */
1340         fdrawline(x2, y1, x2, y2);
1341         
1342         /* top */
1343         if(flag & UI_SELECT) BIF_set_color(bc, COLORSHADE_DARK);
1344         else BIF_set_color(bc, COLORSHADE_WHITE);
1345         fdrawline(x1, y2, x2, y2);
1346
1347         /* left */
1348         fdrawline(x1, y1, x1, y2);
1349         
1350         glColor3ub(0,0,0);
1351         fdrawbox(x1-asp1, y1-asp1, x2+asp1, y2+asp1);
1352 }
1353
1354 /* minimal for menus */
1355 static void ui_emboss_M(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
1356 {
1357         x1+= 1.0;
1358         y1+= 1.0;
1359         x2-= 1.0+asp;
1360         y2-= 1.0+asp;
1361         
1362         
1363         BIF_set_color(bc, COLORSHADE_WHITE);
1364                 
1365         fdrawbox(x1, y1, x2, y2);
1366
1367         /* 
1368         if(flag & UI_SELECT) {
1369                 BIF_set_color(bc, COLORSHADE_LIGHT);
1370                 
1371
1372                 fdrawline(x1, y1, x2, y1);
1373
1374
1375                 fdrawline(x2, y1, x2, y2);
1376         }
1377         else if(flag & UI_ACTIVE) {
1378                 BIF_set_color(bc, COLORSHADE_WHITE);
1379
1380
1381                 fdrawline(x1, y2, x2, y2);
1382         
1383
1384                 fdrawline(x1, y1, x1, y2);
1385         }
1386         else {
1387                 BIF_set_color(bc, COLORSHADE_MEDIUM);
1388                 
1389                 fdrawbox(x1, y1, x2, y2);
1390         }
1391         */
1392 }
1393
1394
1395 /* nothing! */
1396 static void ui_emboss_N(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int sel)
1397 {
1398 }
1399
1400 /* pulldown menu */
1401 static void ui_emboss_P(BIFColorID bc, float asp, float x1, float y1, float x2, float y2, int flag)
1402 {
1403
1404         if(flag & UI_ACTIVE) {
1405                 BIF_set_color(bc, COLORSHADE_DARK);
1406                 glRectf(x1-1, y1, x2+2, y2);
1407
1408         } else {
1409                 BIF_set_color(bc, COLORSHADE_MEDIUM);
1410                 glRectf(x1-1, y1, x2+2, y2);
1411         }
1412
1413         glDisable(GL_BLEND);
1414
1415 }
1416
1417 static void ui_emboss_slider(uiBut *but, float fac)
1418 {
1419         float h;
1420         float x1;
1421         float y1;
1422         float x2;
1423         float y2;
1424
1425         h= (but->y2-but->y1);
1426
1427         x1= but->x1; x2= but->x2;
1428         y1= but->y1; y2= but->y2;
1429
1430         /* the slider background line */
1431
1432         glShadeModel(GL_SMOOTH);
1433         glBegin(GL_QUADS);
1434
1435         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
1436
1437         glVertex2f(x1,y1-4);
1438         glVertex2f(x2-h,y1-4);
1439
1440         BIF_set_color(BUTGREY, COLORSHADE_HILITE);
1441
1442         glVertex2f(x2-h,y2+2);
1443         glVertex2f(x1,y2+2);
1444
1445         glEnd();
1446
1447         /*BIF_set_color(but->col, COLORSHADE_DARK);
1448         glRectf(but->x1, but->y1, but->x2, but->y2);
1449         glColor3ub(0,0,0);
1450         ui_draw_outlineX(but->x1+1, but->y1+1, but->x2-1, but->y2-1, but->aspect);
1451         */
1452
1453         /* the movable slider */
1454         if(but->flag & UI_SELECT) BIF_set_color(but->col, COLORSHADE_WHITE);
1455         else BIF_set_color(but->col, COLORSHADE_GREY);
1456
1457         glShadeModel(GL_SMOOTH);
1458         glBegin(GL_QUADS);
1459
1460         BIF_set_color(BUTGREY, COLORSHADE_GREY);
1461
1462         glVertex2f(x1,y1-4);
1463         glVertex2f(x1+fac,y1-4);
1464
1465         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
1466
1467         glVertex2f(x1+fac,y2+2);
1468         glVertex2f(x1,y2+2);
1469
1470         glEnd();
1471         
1472
1473         /* slider handle center */
1474         glShadeModel(GL_SMOOTH);
1475         glBegin(GL_QUADS);
1476
1477         BIF_set_color(BUTGREY, COLORSHADE_MEDIUM);
1478         glVertex2f(x1+fac-1,y1-4);
1479         glVertex2f(x1+fac+2,y1-4);
1480         BIF_set_color(BUTGREY, COLORSHADE_WHITE);
1481         glVertex2f(x1+fac+2,y2+2);
1482         glVertex2f(x1+fac-1,y2+2);
1483
1484         glEnd();
1485         
1486         /* slider handle left bevel */
1487         BIF_set_color(BUTGREY, COLORSHADE_WHITE);
1488         fdrawline(x1+fac-1, y2+2, x1+fac-1, y1-4);
1489         
1490         /* slider handle right bevel */
1491         BIF_set_color(BUTGREY, COLORSHADE_GREY);
1492         fdrawline(x1+fac+2, y2+2, x1+fac+2, y1-4);
1493
1494
1495 /*
1496         BIF_set_color(BUTGREY, COLORSHADE_WHITE);
1497         fdrawline(x1+fac-1, y2+2, x1+fac+h-1, y2+2);
1498         fdrawline(x1+fac-1, y1-4, x1+fac-1, y2+2);
1499
1500         BIF_set_color(BUTGREY, COLORSHADE_GREY);
1501         fdrawline(x1+fac-1, y1-4, x1+fac+h-1, y1-4);
1502         fdrawline(x1+fac+h-1, y1-4, x1+fac+h-1, y2+2);
1503 */
1504
1505 }
1506
1507 static void ui_draw_but_BUT(uiBut *but)
1508 {
1509         float x=0.0;
1510         
1511         but->embossfunc(but->col, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1512         
1513         if(but->embossfunc==ui_emboss_TABL) {
1514                 but->flag |= UI_TEXT_LEFT;
1515                 but->flag |= UI_ICON_RIGHT;
1516                 but->flag &= ~UI_ICON_LEFT;
1517         }
1518         
1519         //but->flag |= UI_TEXT_LEFT;
1520
1521         /* check for button text label */
1522         if (but->type == ICONTEXTROW) {
1523                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1524         }
1525         else if(but->drawstr[0]!=0) {
1526   
1527                 /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
1528                  * and offset the text label to accomodate it 
1529                  */
1530                 if ( but->flag & UI_HAS_ICON) {
1531                         if (but->flag & UI_ICON_LEFT) {
1532                                 ui_draw_icon(but, but->icon);
1533
1534                                 if(but->flag & UI_TEXT_LEFT) x= but->x1+24.0;
1535                                 else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1536                         } else if (but->flag & UI_ICON_RIGHT) {
1537                                 ui_draw_icon(but, but->icon);
1538
1539                                 if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
1540                                 else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1541                         }
1542                 }
1543                 else {
1544                         if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
1545                         else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1546                 }
1547                 
1548                 if(but->flag & UI_SELECT) {
1549                         glColor3ub(255,255,255);
1550                 } else {
1551                         glColor3ub(0,0,0);
1552                 }
1553
1554                 glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
1555
1556                 BIF_DrawString(but->font, but->drawstr+but->ofs, (U.transopts & TR_BUTTONS), but->flag & UI_SELECT);
1557         }
1558         /* if there's no text label, then check to see if there's an icon only and draw it */
1559         else if( but->flag & UI_HAS_ICON ) {
1560                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1561         }
1562 }
1563
1564 static void ui_draw_but_MENU(uiBut *but)
1565 {
1566         float x;
1567
1568         but->embossfunc = ui_emboss_MENU;
1569
1570         but->embossfunc(but->col, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1571
1572         but->flag |= UI_TEXT_LEFT;
1573
1574         /* check for button text label */
1575         if (but->type == ICONTEXTROW) {
1576                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1577         }
1578         else if(but->drawstr[0]!=0) {
1579                 
1580                 /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
1581                 and offset the text label to accomodate it */
1582                 if ( (but->flag & UI_HAS_ICON) && (but->flag & UI_ICON_LEFT) ) {
1583                         ui_draw_icon(but, but->icon);
1584
1585                         if(but->flag & UI_TEXT_LEFT) x= but->x1+28.0;
1586                         else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1587                 }
1588                 else {
1589                         if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
1590                         else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1591                 }
1592                 
1593                 if(but->flag & UI_SELECT) {
1594                         glColor3ub(255,255,255);
1595                 } else {
1596                         glColor3ub(0,0,0);
1597                 }
1598
1599                 glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
1600
1601                 BIF_DrawString(but->font, but->drawstr+but->ofs, (U.transopts & TR_BUTTONS), but->flag & UI_SELECT);
1602         }
1603         /* if there's no text label, then check to see if there's an icon only and draw it */
1604         else if( but->flag & UI_HAS_ICON ) {
1605                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1606         }
1607 }
1608
1609 static void ui_draw_but_TOG3(uiBut *but)
1610 {
1611         float x, r, g, b;
1612
1613         but->embossfunc(but->col, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1614         
1615         if( but->flag & UI_HAS_ICON ) {
1616                 ui_draw_icon(but, but->icon);
1617         }
1618         else if(but->drawstr[0]!=0) {
1619                 if(but->flag & UI_SELECT) {
1620                         int ok= 0;
1621                         
1622                         if( but->pointype==CHA ) {
1623                                 if( BTST( *(but->poin+2), but->bitnr )) ok= 1;
1624                         }
1625                         else if( but->pointype ==SHO ) {
1626                                 short *sp= (short *)but->poin;
1627                                 if( BTST( sp[1], but->bitnr )) ok= 1;
1628                         }
1629                         
1630                         if (ok) {
1631                                 glColor3ub(255, 255, 0);
1632                                 r= g= 1.0;
1633                                 b= 0.0;
1634                         } else {
1635                                 glColor3ub(255, 255, 255);
1636                                 r= g= b= 1.0;
1637                         }
1638                 } else {
1639                         glColor3ub(0, 0, 0);
1640                         r= g= b= 0.0;
1641                 }
1642
1643                 if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
1644                 else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1645                 
1646                 glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
1647                 
1648                 BIF_DrawStringRGB(but->font, but->drawstr+but->ofs, (U.transopts & TR_BUTTONS), r, g, b);
1649         }
1650 }
1651
1652 static void ui_draw_but_TEX(uiBut *but)
1653 {
1654         float x;
1655         short pos, sel, t;
1656         char ch;
1657         
1658         /* exception for text buttons using embossF */
1659         sel= but->flag;
1660         if(but->embossfunc==ui_emboss_F) sel |= UI_SELECT;
1661         
1662         but->embossfunc = ui_emboss_TEX;
1663
1664         but->embossfunc(but->col, but->aspect, but->x1, but->y1, but->x2, but->y2, sel);
1665         
1666         sel= but->flag & UI_SELECT;
1667
1668         /* draw cursor */
1669         if(but->pos != -1) {
1670                 
1671                 pos= but->pos+strlen(but->str);
1672                 if(pos >= but->ofs) {
1673                         ch= but->drawstr[pos];
1674                         but->drawstr[pos]= 0;
1675
1676                         t= but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, (U.transopts & TR_BUTTONS)) + 3;
1677
1678                         but->drawstr[pos]= ch;
1679                         glColor3ub(255,0,0);
1680
1681                         glRects(but->x1+t, but->y1+2, but->x1+t+3, but->y2-2);
1682                 }       
1683         }
1684         if(but->drawstr[0]!=0) {
1685                 glColor3ub(255,255,255);
1686                 /*
1687                 if(sel) glColor3ub(255,255,255);
1688                 else glColor3ub(0,0,0);
1689                 */
1690
1691                 if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
1692                 else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1693                 
1694                 glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
1695                 
1696                 BIF_DrawString(but->font, but->drawstr+but->ofs, (U.transopts & TR_BUTTONS), sel);
1697         }
1698 }
1699
1700 static void ui_draw_but_NUM(uiBut *but)
1701 {
1702         
1703         float x;
1704         but->embossfunc = ui_emboss_NUM;
1705
1706         but->embossfunc(but->col, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1707
1708         /* check for button text label */
1709         if (but->type == ICONTEXTROW) {
1710                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1711         }
1712         else if(but->drawstr[0]!=0) {
1713                 
1714                 /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
1715                 and offset the text label to accomodate it */
1716                 if ( (but->flag & UI_HAS_ICON) && (but->flag & UI_ICON_LEFT) ) {
1717                         ui_draw_icon(but, but->icon);
1718
1719                         if(but->flag & UI_TEXT_LEFT) x= but->x1+24.0;
1720                         else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1721                 }
1722                 else {
1723                         if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
1724                         else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1725                 }
1726                 
1727                 if(but->flag & UI_SELECT) {
1728                         glColor3ub(255,255,255);
1729                 } else {
1730                         glColor3ub(0,0,0);
1731                 }
1732
1733                 glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
1734
1735                 BIF_DrawString(but->font, but->drawstr+but->ofs, (U.transopts & TR_BUTTONS), but->flag & UI_SELECT);
1736         }
1737         /* if there's no text label, then check to see if there's an icon only and draw it */
1738         else if( but->flag & UI_HAS_ICON ) {
1739                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd));
1740         }
1741
1742 }
1743
1744 static void ui_draw_but_BUTM(uiBut *but)
1745 {
1746         float x=0;
1747         short len;
1748         char *cpoin;
1749         int sel;
1750
1751         but->embossfunc(but->col, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
1752
1753         /* check for button text label */
1754         if(but->drawstr[0]!=0) {
1755                 
1756                 cpoin= strchr(but->drawstr, '|');
1757                 if(cpoin) *cpoin= 0;
1758
1759                 if(but->embossfunc==ui_emboss_P) {
1760                         if(but->flag & UI_ACTIVE) {
1761                                 glColor3ub(255,255,255);
1762                                 sel = 1;
1763                         } else {
1764                                 glColor3ub(0,0,0);
1765                                 sel = 0;
1766                         }
1767                 }
1768                 else {
1769                         glColor3ub(0,0,0);
1770                         sel = 0;
1771                 }
1772
1773                 /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
1774                 and offset the text label to accomodate it */
1775                 if ( but->flag & UI_HAS_ICON ) {
1776                         if (but->flag & UI_ICON_LEFT ) {
1777                                 ui_draw_icon(but, but->icon);
1778
1779                                 x= but->x1+22.0;
1780                         } else if (but->flag & UI_ICON_RIGHT) {
1781                                 ui_draw_icon(but, but->icon);
1782
1783                                 x= but->x1+4.0;
1784                         }
1785                 }
1786                 else {
1787                         x= but->x1+4.0;
1788                 }
1789
1790                 glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
1791
1792                 BIF_DrawString(but->font, but->drawstr, (U.transopts & TR_BUTTONS), sel);
1793                 
1794                 if(cpoin) {
1795                         len= BIF_GetStringWidth(but->font, cpoin+1, (U.transopts & TR_BUTTONS));
1796                         glRasterPos2f( but->x2 - len*but->aspect-3, (but->y1+but->y2- 9.0)/2.0);
1797                         BIF_DrawString(but->font, cpoin+1, (U.transopts & TR_BUTTONS), but->flag & UI_ACTIVE);
1798                         *cpoin= '|';
1799                 }
1800         }
1801         /* if there's no text label, then check to see if there's an icon only and draw it */
1802         else if( but->flag & UI_HAS_ICON ) {
1803                 ui_draw_icon(but, but->icon);
1804         }
1805 }
1806
1807 static void ui_draw_but_LABEL(uiBut *but)
1808 {
1809         float x;
1810         int sel;
1811
1812         sel= but->min!=0.0;
1813
1814         if(sel) glColor3ub(255,255,255);
1815         else glColor3ub(0,0,0);
1816         
1817         /* check for button text label */
1818         if(but->drawstr[0]!=0) {
1819
1820            /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
1821                 and offset the text label to accomodate it */
1822                 if ( (but->flag & UI_HAS_ICON) && (but->flag & UI_ICON_LEFT) ) {
1823                         ui_draw_icon(but, but->icon);
1824
1825                         if(but->flag & UI_TEXT_LEFT) x= but->x1+24.0;
1826                         else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1827                 }
1828                 else {
1829                         if(but->flag & UI_TEXT_LEFT) x= but->x1+4.0;
1830                         else x= (but->x1+but->x2-but->strwidth+1)/2.0;
1831                 }
1832
1833                 glRasterPos2f( x, (but->y1+but->y2- 9.0)/2.0);
1834
1835                 BIF_DrawString(but->font, but->drawstr+but->ofs, (U.transopts & TR_BUTTONS), sel);
1836         }
1837         /* if there's no text label, then check to see if there's an icon only and draw it */
1838         else if( but->flag & UI_HAS_ICON ) {
1839                 ui_draw_icon(but, but->icon);
1840         }
1841 }
1842
1843 static void ui_draw_but_SEPR(uiBut *but)
1844 {
1845         //float y= (but->y1+but->y2)/2.0;
1846
1847         BIF_set_color(but->col, COLORSHADE_HILITE);
1848         glRectf(but->x1-2, but->y1-1, but->x2+2, but->y2);
1849
1850 }
1851
1852 static void ui_draw_but_LINK(uiBut *but)
1853 {
1854         ui_draw_icon(but, but->icon);
1855 }
1856
1857
1858 static void ui_draw_but(uiBut *but)
1859 {
1860         double value;
1861         float fac, x1, y1, x2, y2, *fp;
1862         short a;
1863         char colr, colg, colb;
1864         
1865         if(but==0) return;
1866
1867         if(but->block->frontbuf==UI_NEED_DRAW_FRONT) {
1868                 but->block->frontbuf= UI_HAS_DRAW_FRONT;
1869         
1870                 glDrawBuffer(GL_FRONT);
1871                 if(but->win==curarea->headwin) curarea->head_swap= WIN_FRONT_OK;
1872                 else curarea->win_swap= WIN_FRONT_OK;
1873         }
1874         
1875         switch (but->type) {
1876
1877         case BUT: 
1878         case ROW: 
1879         case TOG:
1880         case TOGR: 
1881         case TOGN:
1882         case ICONTOG:
1883         case KEYEVT:
1884         case IDPOIN:
1885                 ui_draw_but_BUT(but);
1886                 break;
1887         case NUM:
1888                 ui_draw_but_NUM(but);
1889                 break;
1890         case TEX:
1891                 ui_draw_but_TEX(but);
1892                 break;
1893
1894         case BUTM:
1895         case BLOCK:
1896                 ui_draw_but_BUTM(but);
1897                 break;
1898                 
1899         case ICONROW:
1900                 ui_draw_but_BUT(but);
1901                 
1902                 /* draw arriws, icon is standard RGB */
1903                 a= (but->y1+but->y2)/2;
1904                 
1905                 glColor3ub(0,0,0);
1906                 sdrawline((short)(but->x1-1), (short)(a-2), (short)(but->x1-1), (short)(a+2));
1907                 sdrawline((short)(but->x1-2), (short)(a-1), (short)(but->x1-2), (short)(a+1));
1908                 sdrawline((short)(but->x1-3), a, (short)(but->x1-3), a);
1909                 glColor3ub(255,255,255);
1910                 sdrawline((short)(but->x1-3), (short)(a-1), (short)(but->x1-1), (short)(a-3));
1911                 
1912                 glColor3ub(0,0,0);
1913                 sdrawline((short)(but->x2+1), (short)(a-2), (short)(but->x2+1), (short)(a+2));
1914                 sdrawline((short)(but->x2+2), (short)(a-1), (short)(but->x2+2), (short)(a+1));
1915                 sdrawline((short)(but->x2+3), a, (short)(but->x2+3), a);
1916                 glColor3ub(255,255,255);
1917                 sdrawline((short)(but->x2+3), (short)(a-1), (short)(but->x2+1), (short)(a-3));
1918
1919                 break;
1920                 
1921         case ICONTEXTROW:
1922                 ui_draw_but_BUT(but);
1923                 
1924                 /* teken pijltjes, icon is standaard RGB */
1925                 a= (but->y1+but->y2)/2;
1926                 
1927                 glColor3ub(0,0,0);
1928                 sdrawline((short)(but->x1-1), (short)(a-2), (short)(but->x1-1), (short)(a+2));
1929                 sdrawline((short)(but->x1-2), (short)(a-1), (short)(but->x1-2), (short)(a+1));
1930                 sdrawline((short)(but->x1-3), a, (short)(but->x1-3), a);
1931                 glColor3ub(255,255,255);
1932                 sdrawline((short)(but->x1-3), (short)(a-1), (short)(but->x1-1), (short)(a-3));
1933
1934                 glColor3ub(0,0,0);
1935                 sdrawline((short)(but->x2+1), (short)(a-2), (short)(but->x2+1), (short)(a+2));
1936                 sdrawline((short)(but->x2+2), (short)(a-1), (short)(but->x2+2), (short)(a+1));
1937                 sdrawline((short)(but->x2+3), a, (short)(but->x2+3), a);
1938                 glColor3ub(255,255,255);
1939                 sdrawline((short)(but->x2+3), (short)(a-1), (short)(but->x2+1), (short)(a-3));
1940
1941                 break;
1942
1943         case MENU:
1944         
1945                 ui_draw_but_MENU(but);
1946
1947                 /* when sufficient space: darw symbols 
1948                 if(but->strwidth+10 < but->x2-but->x1) {
1949                         
1950
1951
1952
1953
1954                         int h;
1955
1956                         h= but->y2- but->y1;
1957                         x1= but->x2-0.66*h; x2= x1+.33*h;
1958                         y1= but->y1+.42*h; y2= y1+.16*h;
1959
1960                         glColor3ub(0,0,0);
1961                         glRecti(x1,  y1,  x2,  y2);
1962                         glColor3ub(255,255,255);
1963                         glRecti(x1-1,  y1+1,  x2-1,  y2+1);
1964
1965                 }*/
1966                 break;
1967                 
1968         case NUMSLI:
1969         case HSVSLI:
1970         
1971                 ui_draw_but_BUT(but);
1972                 
1973                 /* the slider */
1974
1975                 x1= but->x1; x2= but->x2;
1976                 y1= but->y1; y2= but->y2;
1977                 
1978                 but->x1= (but->x1+but->x2)/2;
1979                 but->x2-= 9;
1980                 but->y1= -2+(but->y1+but->y2)/2;
1981                 but->y2= but->y1+6;
1982                 
1983                 value= ui_get_but_val(but);
1984                 fac= (value-but->min)*(but->x2-but->x1-but->y2+but->y1)/(but->max - but->min);
1985                 ui_emboss_slider(but, fac);
1986                 
1987                 but->x1= x1; but->x2= x2;
1988                 but->y1= y1; but->y2= y2;
1989                 
1990                 break;
1991                 
1992         case TOG3:
1993                 ui_draw_but_TOG3(but);
1994                 break;
1995
1996         case LABEL:
1997                 ui_draw_but_LABEL(but);
1998                 break;
1999
2000         case SLI:
2001                 break;
2002
2003         case SCROLL:
2004                 break;
2005                 
2006         case SEPR:
2007                 ui_draw_but_SEPR(but);
2008                 break;
2009                 
2010         case COL:
2011                 ui_draw_but_BUT(but);
2012                 
2013                 if( but->pointype==FLO ) {
2014                         fp= (float *)but->poin;
2015                         colr= floor(255.0*fp[0]+0.5);
2016                         colg= floor(255.0*fp[1]+0.5);
2017                         colb= floor(255.0*fp[2]+0.5);
2018                 }
2019                 else {
2020                         char *cp= (char *)but->poin;
2021                         colr= cp[0];
2022                         colg= cp[1];
2023                         colb= cp[2];
2024                 }
2025                 glColor3ub(colr,  colg,  colb);
2026                 glRects((short)(but->x1+2), (short)(but->y1+2), (short)(but->x2-2), (short)(but->y2-2));
2027                 break;
2028
2029         case LINK:
2030                 ui_draw_but_LINK(but);
2031                 break;
2032
2033         case INLINK:
2034                 ui_draw_but_LINK(but);
2035                 break;
2036         }
2037 }
2038
2039 /* --------- generic helper drawng calls ---------------- */
2040
2041 /* supposes you draw the actual box atop of this. */
2042 void uiSoftShadow(float minx, float miny, float maxx, float maxy, float rad, int alpha)
2043 {
2044
2045         glShadeModel(GL_SMOOTH);
2046         glEnable(GL_BLEND);
2047         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
2048         
2049         /* quads start left-top, clockwise */
2050         
2051         /* left */
2052         glBegin(GL_POLYGON);
2053         glColor4ub(0, 0, 0, 0);
2054         glVertex2f( minx-rad, maxy-rad);
2055         glColor4ub(0, 0, 0, alpha);
2056         glVertex2f( minx+rad, maxy-rad);
2057         glColor4ub(0, 0, 0, alpha);
2058         glVertex2f( minx+rad, miny+rad);
2059         glColor4ub(0, 0, 0, 0);
2060         glVertex2f( minx-rad, miny-rad);
2061         glEnd();
2062
2063         /* bottom */
2064         glBegin(GL_POLYGON);
2065         glColor4ub(0, 0, 0, alpha);
2066         glVertex2f( minx+rad, miny+rad);
2067         glColor4ub(0, 0, 0, alpha);
2068         glVertex2f( maxx-rad, miny+rad);
2069         glColor4ub(0, 0, 0, 0);
2070         glVertex2f( maxx+rad, miny-rad);
2071         glColor4ub(0, 0, 0, 0);
2072         glVertex2f( minx-rad, miny-rad);
2073         glEnd();
2074
2075         /* right */
2076         glBegin(GL_POLYGON);
2077         glColor4ub(0, 0, 0, alpha);
2078         glVertex2f( maxx-rad, maxy-rad);
2079         glColor4ub(0, 0, 0, 0);
2080         glVertex2f( maxx+rad, maxy-rad);
2081         glColor4ub(0, 0, 0, 0);
2082         glVertex2f( maxx+rad, miny-rad);
2083         glColor4ub(0, 0, 0, alpha);
2084         glVertex2f( maxx-rad, miny+rad);
2085         glEnd();
2086
2087         glDisable(GL_BLEND);
2088         glShadeModel(GL_FLAT);
2089 }
2090
2091
2092 #define UI_RB_ALPHA 16
2093 static int roundboxtype= 15;
2094
2095 void uiSetRoundBox(int type)
2096 {
2097         roundboxtype= type;
2098 }
2099
2100 void gl_round_box_topshade(float minx, float miny, float maxx, float maxy, float rad)
2101 {
2102         float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
2103                           {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
2104         char col[7]= {140, 165, 195, 210, 230, 245, 255};
2105         int a;
2106         char alpha=255;
2107         
2108         if(roundboxtype & UI_RB_ALPHA) alpha= 128;
2109         
2110         /* mult */
2111         for(a=0; a<7; a++) {
2112                 vec[a][0]*= rad; vec[a][1]*= rad;
2113         }
2114
2115         /* shades from grey->white->grey */
2116         glBegin(GL_LINE_STRIP);
2117         
2118         if(roundboxtype & 3) {
2119                 /* corner right-top */
2120                 glColor4ub(140, 140, 140, alpha);
2121                 glVertex2f( maxx, maxy-rad);
2122                 for(a=0; a<7; a++) {
2123                         glColor4ub(col[a], col[a], col[a], alpha);
2124                         glVertex2f( maxx-vec[a][1], maxy-rad+vec[a][0]);
2125                 }
2126                 glColor4ub(255, 255, 255, alpha);
2127                 glVertex2f( maxx-rad, maxy);
2128         
2129                 
2130                 /* corner left-top */
2131                 glVertex2f( minx+rad, maxy);
2132                 for(a=0; a<7; a++) {
2133                         glColor4ub(col[6-a], col[6-a], col[6-a], alpha);
2134                         glVertex2f( minx+rad-vec[a][0], maxy-vec[a][1]);
2135                 }
2136                 glVertex2f( minx, maxy-rad);
2137         }
2138         else {
2139                 glColor4ub(255, 255, 255, alpha);
2140                 glVertex2f( minx, maxy);
2141                 glVertex2f( maxx, maxy);
2142         }
2143         
2144         glEnd();
2145 }
2146
2147
2148 void gl_round_box(float minx, float miny, float maxx, float maxy, float rad)
2149 {
2150         float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
2151                           {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
2152         int a;
2153         
2154         /* mult */
2155         for(a=0; a<7; a++) {
2156                 vec[a][0]*= rad; vec[a][1]*= rad;
2157         }
2158
2159         /* start with corner right-bottom */
2160         if(roundboxtype & 4) {
2161                 glVertex2f( maxx-rad, miny);
2162                 for(a=0; a<7; a++) {
2163                         glVertex2f( maxx-rad+vec[a][0], miny+vec[a][1]);
2164                 }
2165                 glVertex2f( maxx, miny+rad);
2166         }
2167         else glVertex2f( maxx, miny);
2168         
2169         /* corner right-top */
2170         if(roundboxtype & 2) {
2171                 glVertex2f( maxx, maxy-rad);
2172                 for(a=0; a<7; a++) {
2173                         glVertex2f( maxx-vec[a][1], maxy-rad+vec[a][0]);
2174                 }
2175                 glVertex2f( maxx-rad, maxy);
2176         }
2177         else glVertex2f( maxx, maxy);
2178         
2179         /* corner left-top */
2180         if(roundboxtype & 1) {
2181                 glVertex2f( minx+rad, maxy);
2182                 for(a=0; a<7; a++) {
2183                         glVertex2f( minx+rad-vec[a][0], maxy-vec[a][1]);
2184                 }
2185                 glVertex2f( minx, maxy-rad);
2186         }
2187         else glVertex2f( minx, maxy);
2188         
2189         /* corner left-bottom */
2190         if(roundboxtype & 8) {
2191                 glVertex2f( minx, miny+rad);
2192                 for(a=0; a<7; a++) {
2193                         glVertex2f( minx+vec[a][1], miny+rad-vec[a][0]);
2194                 }
2195                 glVertex2f( minx+rad, miny);
2196         }
2197         else glVertex2f( minx, miny);
2198         
2199 }
2200
2201 /* for headers and floating panels */
2202 void uiRoundBoxEmboss(float minx, float miny, float maxx, float maxy, float rad)
2203 {
2204         float color[4];
2205         
2206         if(roundboxtype & UI_RB_ALPHA) {
2207                 glGetFloatv(GL_CURRENT_COLOR, color);
2208                 color[3]= 0.5;
2209                 glColor4fv(color);
2210                 glEnable( GL_BLEND );
2211                 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
2212         }
2213         
2214         /* solid part */
2215         glBegin(GL_POLYGON);
2216         gl_round_box(minx, miny, maxx, maxy, rad);
2217         glEnd();
2218         
2219         /* set antialias line */
2220         glEnable( GL_LINE_SMOOTH );
2221         glEnable( GL_BLEND );
2222         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
2223
2224         gl_round_box_topshade(minx+1, miny+1, maxx-1, maxy-1, rad);
2225
2226         if(roundboxtype & UI_RB_ALPHA) glColor4ub(0,0,0, 128); else glColor4ub(0,0,0, 255);
2227         glBegin(GL_LINE_LOOP);
2228         gl_round_box(minx, miny, maxx, maxy, rad);
2229         glEnd();
2230    
2231         glDisable( GL_BLEND );
2232         glDisable( GL_LINE_SMOOTH );
2233  
2234
2235 }
2236
2237 /* plain antialiased unfilled rectangle */
2238 void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad)
2239 {
2240         float color[4];
2241         
2242         if(roundboxtype & UI_RB_ALPHA) {
2243                 glGetFloatv(GL_CURRENT_COLOR, color);
2244                 color[3]= 0.5;
2245                 glColor4fv(color);
2246                 glEnable( GL_BLEND );
2247                 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
2248         }
2249         
2250         /* set antialias line */
2251         glEnable( GL_LINE_SMOOTH );
2252         glEnable( GL_BLEND );
2253         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
2254
2255         glBegin(GL_LINE_LOOP);
2256         gl_round_box(minx, miny, maxx, maxy, rad);
2257         glEnd();
2258    
2259         glDisable( GL_BLEND );
2260         glDisable( GL_LINE_SMOOTH );
2261 }
2262
2263
2264
2265 /* plain antialiased filled box */
2266 void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad)
2267 {
2268         float color[4];
2269         
2270         if(roundboxtype & UI_RB_ALPHA) {
2271                 glGetFloatv(GL_CURRENT_COLOR, color);
2272                 color[3]= 0.5;
2273                 glColor4fv(color);
2274                 glEnable( GL_BLEND );
2275                 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
2276         }
2277         
2278         /* solid part */
2279         glBegin(GL_POLYGON);
2280         gl_round_box(minx, miny, maxx, maxy, rad);
2281         glEnd();
2282         
2283         /* set antialias line */
2284         glEnable( GL_LINE_SMOOTH );
2285         glEnable( GL_BLEND );
2286         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
2287
2288         glBegin(GL_LINE_LOOP);
2289         gl_round_box(minx, miny, maxx, maxy, rad);
2290         glEnd();
2291    
2292         glDisable( GL_BLEND );
2293         glDisable( GL_LINE_SMOOTH );
2294 }
2295
2296
2297
2298
2299 void uiDrawMenuBox(float minx, float miny, float maxx, float maxy)
2300 {
2301         BIF_set_color(MENUCOL, COLORSHADE_HILITE);
2302
2303         glRectf(minx, miny, maxx, maxy);
2304         
2305         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2306         glEnable(GL_BLEND);
2307
2308         glColor4ub(0, 0, 0, 100);
2309         fdrawline(minx+4, miny, maxx+1, miny);
2310         fdrawline(maxx+1, miny, maxx+1, maxy-4);
2311         
2312         glColor4ub(0, 0, 0, 80);
2313         fdrawline(minx+4, miny-1, maxx+1, miny-1);
2314         fdrawline(maxx+1, miny-1, maxx+1, maxy-4);
2315
2316         glColor4ub(0, 0, 0, 55);
2317         fdrawline(minx+4, miny-2, maxx+2, miny-2);
2318         fdrawline(maxx+2, miny-2, maxx+2, maxy-4);
2319
2320         glColor4ub(0, 0, 0, 35);
2321         fdrawline(minx+4, miny-3, maxx+3, miny-3);
2322         fdrawline(maxx+3, miny-3, maxx+3, maxy-4);
2323
2324         glColor4ub(0, 0, 0, 20);
2325         fdrawline(minx+4, miny-4, maxx+4, miny-4);
2326         fdrawline(maxx+4, miny-4, maxx+4, maxy-4);
2327
2328         glDisable(GL_BLEND);
2329         
2330         /* below */
2331         //glColor3ub(0,0,0);
2332         //fdrawline(minx, miny, maxx, miny);
2333
2334         /* right */
2335         //fdrawline(maxx, miny, maxx, maxy);
2336         
2337         /* top */
2338         //glColor3ub(255,255,255);
2339         //fdrawline(minx, maxy, maxx, maxy);
2340
2341         /* left */
2342         //fdrawline(minx, miny, minx, maxy);
2343
2344 }
2345
2346 static void ui_draw_linkline(uiBut *but, uiLinkLine *line)
2347 {
2348         float vec1[2], vec2[2];
2349
2350         if(line->from==NULL || line->to==NULL) return;
2351         
2352         if(but->block->frontbuf==UI_NEED_DRAW_FRONT) {
2353                 but->block->frontbuf= UI_HAS_DRAW_FRONT;
2354         
2355                 glDrawBuffer(GL_FRONT);
2356                 if(but->win==curarea->headwin) curarea->head_swap= WIN_FRONT_OK;
2357                 else curarea->win_swap= WIN_FRONT_OK;
2358         }
2359
2360         vec1[0]= (line->from->x1+line->from->x2)/2.0;
2361         vec1[1]= (line->from->y1+line->from->y2)/2.0;
2362         vec2[0]= (line->to->x1+line->to->x2)/2.0;
2363         vec2[1]= (line->to->y1+line->to->y2)/2.0;
2364         
2365         if(line->flag & UI_SELECT) BIF_set_color(but->col, COLORSHADE_LIGHT);
2366         else glColor3ub(0,0,0);
2367         fdrawline(vec1[0], vec1[1], vec2[0], vec2[1]);
2368 }
2369
2370 static void ui_draw_links(uiBlock *block)
2371 {
2372         uiBut *but;
2373         uiLinkLine *line;
2374         
2375         but= block->buttons.first;
2376         while(but) {
2377                 if(but->type==LINK && but->link) {
2378                         line= but->link->lines.first;
2379                         while(line) {
2380                                 ui_draw_linkline(but, line);
2381                                 line= line->next;
2382                         }
2383                 }
2384                 but= but->next;
2385         }       
2386 }
2387
2388
2389
2390 /* ******************* block calc ************************* */
2391
2392 void uiTextBoundsBlock(uiBlock *block, int addval)
2393 {
2394         uiBut *bt;
2395         int i = 0, j;
2396         
2397         bt= block->buttons.first;
2398         while(bt) {
2399                 if(bt->type!=SEPR) {
2400                         j= BIF_GetStringWidth(bt->font, bt->drawstr, (U.transopts & TR_BUTTONS));
2401
2402                         if(j > i) i = j;
2403                 }
2404                 bt= bt->next;
2405         }
2406
2407         
2408         bt= block->buttons.first;
2409         while(bt) {
2410                 bt->x2 = i + addval;
2411                 bt= bt->next;
2412         }
2413 }
2414
2415
2416 void uiBoundsBlock(uiBlock *block, int addval)
2417 {
2418         uiBut *bt;
2419         
2420         if(block->buttons.first==NULL) {
2421                 if(block->panel) {
2422                         block->minx= 0.0; block->maxx= block->panel->sizex;
2423                         block->miny= 0.0; block->maxy= block->panel->sizey;
2424                 }
2425         }
2426         else {
2427         
2428                 block->minx= block->miny= 10000;
2429                 block->maxx= block->maxy= -10000;
2430                 
2431                 bt= block->buttons.first;
2432                 while(bt) {
2433                         if(bt->x1 < block->minx) block->minx= bt->x1;
2434                         if(bt->y1 < block->miny) block->miny= bt->y1;
2435         
2436                         if(bt->x2 > block->maxx) block->maxx= bt->x2;
2437                         if(bt->y2 > block->maxy) block->maxy= bt->y2;
2438                         
2439                         bt= bt->next;
2440                 }
2441                 
2442                 block->minx -= addval;
2443                 block->miny -= addval;
2444                 block->maxx += addval;
2445                 block->maxy += addval;
2446         }
2447 }
2448
2449 static void ui_positionblock(uiBlock *block, uiBut *but)
2450 {
2451         /* position block relative to but */
2452         uiBut *bt;
2453         int xsize, ysize, xof=0, yof=0;
2454         
2455         block->minx= block->miny= 10000;
2456         block->maxx= block->maxy= -10000;
2457         
2458         bt= block->buttons.first;
2459         while(bt) {
2460                 if(bt->x1 < block->minx) block->minx= bt->x1;
2461                 if(bt->y1 < block->miny) block->miny= bt->y1;
2462
2463                 if(bt->x2 > block->maxx) block->maxx= bt->x2;
2464                 if(bt->y2 > block->maxy) block->maxy= bt->y2;
2465                 
2466                 bt= bt->next;
2467         }
2468         
2469         block->minx-= 2.0; block->miny-= 2.0;
2470         block->maxx+= 2.0; block->maxy+= 2.0;
2471         
2472         xsize= block->maxx - block->minx;
2473         ysize= block->maxy - block->miny;
2474         
2475         if(but) {
2476                 rctf butrct;
2477                 short left=0, right=0, top=0, down=0;
2478                 short dir1, dir2 = 0;
2479
2480                 butrct.xmin= but->x1; butrct.xmax= but->x2;
2481                 butrct.ymin= but->y1; butrct.ymax= but->y2;
2482                 
2483                 if(but->block->panel) {
2484                         butrct.xmin += but->block->panel->ofsx;
2485                         butrct.ymin += but->block->panel->ofsy;
2486                         butrct.xmax += but->block->panel->ofsx;
2487                         butrct.ymax += but->block->panel->ofsy;
2488                 }
2489
2490                 /* added this for submenu's... */
2491                 Mat4CpyMat4(UIwinmat, block->winmat);
2492
2493                 ui_graphics_to_window(block->win, &butrct.xmin, &butrct.ymin);
2494                 ui_graphics_to_window(block->win, &butrct.xmax, &butrct.ymax);
2495                 block->parentrct= butrct;       // will use that for pulldowns later
2496
2497                 if( butrct.xmin-xsize > 0.0) left= 1;
2498                 if( butrct.xmax+xsize < G.curscreen->sizex) right= 1;
2499                 if( butrct.ymin-ysize > 0.0) down= 1;
2500                 if( butrct.ymax+ysize < G.curscreen->sizey) top= 1;
2501                 
2502                 dir1= block->direction;
2503                 if(dir1==UI_LEFT || dir1==UI_RIGHT) dir2= UI_DOWN;
2504                 if(dir1==UI_TOP || dir1==UI_DOWN) dir2= UI_LEFT;
2505                 
2506                 if(dir1==UI_LEFT && left==0) dir1= UI_RIGHT;
2507                 if(dir1==UI_RIGHT && right==0) dir1= UI_LEFT;
2508                         /* this is aligning, not append! */
2509                 if(dir2==UI_LEFT && right==0) dir2= UI_RIGHT;
2510                 if(dir2==UI_RIGHT && left==0) dir2= UI_LEFT;
2511                 
2512                 if(dir1==UI_TOP && top==0) dir1= UI_DOWN;
2513                 if(dir1==UI_DOWN && down==0) dir1= UI_TOP;
2514                 if(dir2==UI_TOP && top==0) dir2= UI_DOWN;
2515                 if(dir2==UI_DOWN && down==0) dir2= UI_TOP;
2516
2517                 if(dir1==UI_LEFT) {
2518                         xof= but->x1 - block->maxx;
2519                         if(dir2==UI_TOP) yof= but->y1 - block->miny;
2520                         else yof= but->y2 - block->maxy;
2521                 }
2522                 else if(dir1==UI_RIGHT) {
2523                         xof= but->x2 - block->minx;
2524                         if(dir2==UI_TOP) yof= but->y1 - block->miny;
2525                         else yof= but->y2 - block->maxy;
2526                 }
2527                 else if(dir1==UI_TOP) {
2528                         yof= but->y2 - block->miny+1;
2529                         if(dir2==UI_RIGHT) xof= but->x2 - block->maxx;
2530                         else xof= but->x1 - block->minx;
2531                 }
2532                 else if(dir1==UI_DOWN) {
2533                         yof= but->y1 - block->maxy-1;
2534                         if(dir2==UI_RIGHT) xof= but->x2 - block->maxx;
2535                         else xof= but->x1 - block->minx;
2536                 }
2537
2538                 // apply requested offset in the block
2539
2540                 xof += block->xofs;
2541                 yof += block->yofs;
2542                 
2543                 if(but->block->panel) {
2544                         xof += but->block->panel->ofsx;
2545                         yof += but->block->panel->ofsy;
2546                 }
2547         }
2548         
2549         /* apply */
2550         bt= block->buttons.first;
2551         while(bt) {
2552                 bt->x1 += xof;
2553                 bt->x2 += xof;
2554                 bt->y1 += yof;
2555                 bt->y2 += yof;
2556                 
2557                 ui_graphics_to_window(block->win, &bt->x1, &bt->y1);
2558                 ui_graphics_to_window(block->win, &bt->x2, &bt->y2);
2559
2560                 bt->aspect= 1.0;
2561                 
2562                 bt= bt->next;
2563         }
2564         
2565         block->minx += xof;
2566         block->miny += yof;
2567         block->maxx += xof;
2568         block->maxy += yof;
2569         
2570         ui_graphics_to_window(block->win, &block->minx, &block->miny);
2571         ui_graphics_to_window(block->win, &block->maxx, &block->maxy);
2572
2573 }
2574
2575
2576 static void ui_autofill(uiBlock *block)
2577 {
2578         uiBut *but;
2579         float *maxw, *maxh, startx = 0, starty, height = 0;
2580         float totmaxh;
2581         int rows=0, /*  cols=0, */ i, lasti;
2582         
2583         
2584         /* first count rows */
2585         but= block->buttons.last;
2586         rows= but->x1+1;
2587
2588         /* calculate max width / height for each row */
2589         maxw= MEM_callocN(sizeof(float)*rows, "maxw");
2590         maxh= MEM_callocN(sizeof(float)*rows, "maxh");
2591         but= block->buttons.first;
2592         while(but) {
2593                 i= but->x1;
2594                 if( maxh[i] < but->y2) maxh[i]= but->y2;
2595                 maxw[i] += but->x2;
2596                 but= but->next;
2597         }
2598         
2599         totmaxh= 0.0;
2600         for(i=0; i<rows; i++) totmaxh+= maxh[i];
2601         
2602         /* apply widths/heights */
2603         starty= block->maxy;
2604         but= block->buttons.first;
2605         lasti= -1;
2606         while(but) {
2607                 
2608                 i= but->x1;
2609
2610                 if(i!=lasti) {
2611                         startx= block->minx;
2612                         height= (maxh[i]*(block->maxy-block->miny))/totmaxh;
2613                         starty-= height;
2614                         lasti= i;
2615                 }
2616                 
2617                 but->y1= starty+but->aspect;
2618                 but->y2= but->y1+height-but->aspect;
2619                 
2620                 but->x2= (but->x2*(block->maxx-block->minx))/maxw[i];
2621                 but->x1= startx+but->aspect;
2622                 
2623                 startx+= but->x2;
2624                 but->x2+= but->x1-but->aspect;
2625                 
2626                 ui_check_but(but);
2627                 
2628                 but= but->next;
2629         }
2630         
2631         MEM_freeN(maxw); MEM_freeN(maxh);       
2632         block->autofill= 0;
2633 }
2634
2635 void uiDrawBlock(uiBlock *block)
2636 {
2637         uiBut *but;
2638
2639         if(block->autofill) ui_autofill(block);
2640         if(block->minx==0.0 && block->maxx==0.0) uiBoundsBlock(block, 0);
2641
2642         ui_panel_push(block); // panel matrix
2643         
2644         if(block->flag & UI_BLOCK_LOOP) {
2645                 BIF_set_color(block->col, COLORSHADE_HILITE);
2646                 uiDrawMenuBox(block->minx, block->miny, block->maxx, block->maxy);
2647         }
2648         else if(block->panel) ui_draw_panel(block);
2649         
2650         for (but= block->buttons.first; but; but= but->next) {
2651                 ui_draw_but(but);
2652         }
2653
2654         ui_draw_links(block);
2655         ui_panel_pop(block); // matrix restored
2656 }
2657
2658 /* ************* MENUBUTS *********** */
2659
2660 typedef struct {
2661         char *str;
2662         int retval;
2663 } MenuEntry;
2664
2665 typedef struct {
2666         char *instr;
2667         char *title;
2668         
2669         MenuEntry *items;
2670         int nitems, itemssize;
2671 } MenuData;
2672
2673 static MenuData *menudata_new(char *instr) {
2674         MenuData *md= MEM_mallocN(sizeof(*md), "MenuData");
2675
2676         md->instr= instr;
2677         md->title= NULL;
2678         md->items= NULL;
2679         md->nitems= md->itemssize= 0;
2680         
2681         return md;
2682 }
2683
2684 static void menudata_set_title(MenuData *md, char *title) {
2685         if (!md->title)
2686                 md->title= title;
2687 }
2688
2689 static void menudata_add_item(MenuData *md, char *str, int retval) {
2690         if (md->nitems==md->itemssize) {
2691                 int nsize= md->itemssize?(md->itemssize<<1):1;
2692                 MenuEntry *oitems= md->items;
2693                 
2694                 md->items= MEM_mallocN(nsize*sizeof(*md->items), "md->items");
2695                 if (oitems) {
2696                         memcpy(md->items, oitems, md->nitems*sizeof(*md->items));
2697                         MEM_freeN(oitems);
2698                 }
2699                 
2700                 md->itemssize= nsize;
2701         }
2702         
2703         md->items[md->nitems].str= str;
2704         md->items[md->nitems].retval= retval;
2705         md->nitems++;
2706 }
2707
2708 static void menudata_free(MenuData *md) {
2709         MEM_freeN(md->instr);
2710         if (md->items)
2711                 MEM_freeN(md->items);
2712         MEM_freeN(md);
2713 }
2714
2715         /**
2716          * Parse menu description strings, string is of the
2717          * form "[sss%t|]{(sss[%xNN]|), (%l|)}", ssss%t indicates the
2718          * menu title, sss or sss%xNN indicates an option, 
2719          * if %xNN is given then NN is the return value if
2720          * that option is selected otherwise the return value
2721          * is the index of the option (starting with 1). %l
2722          * indicates a seperator.
2723          * 
2724          * @param str String to be parsed.
2725          * @retval new menudata structure, free with menudata_free()
2726          */
2727 static MenuData *decompose_menu_string(char *str) 
2728 {
2729         char *instr= BLI_strdup(str);
2730         MenuData *md= menudata_new(instr);
2731         char *nitem= NULL, *s= instr;
2732         int nretval= 1, nitem_is_title= 0;
2733         
2734         while (1) {
2735                 char c= *s;
2736
2737                 if (c=='%') {
2738                         if (s[1]=='x') {
2739                                 nretval= atoi(s+2);
2740
2741                                 *s= '\0';
2742                                 s++;
2743                         } else if (s[1]=='t') {
2744                                 nitem_is_title= 1;
2745
2746                                 *s= '\0';
2747                                 s++;
2748                         } else if (s[1]=='l') {
2749                                 nitem= "%l";
2750                                 s++;
2751                         }
2752                 } else if (c=='|' || c=='\0') {
2753                         if (nitem) {
2754                                 *s= '\0';
2755
2756                                 if (nitem_is_title) {
2757                                         menudata_set_title(md, nitem);
2758                                         nitem_is_title= 0;
2759                                 } else {
2760                                         menudata_add_item(md, nitem, nretval);
2761                                         nretval= md->nitems+1;
2762                                 } 
2763                                 
2764                                 nitem= NULL;
2765                         }
2766                         
2767                         if (c=='\0')
2768                                 break;
2769                 } else if (!nitem)
2770                         nitem= s;
2771                 
2772                 s++;
2773         }
2774         
2775         return md;
2776 }
2777
2778 static void ui_set_name_menu(uiBut *but, int value)
2779 {
2780         MenuData *md;
2781         int i;
2782         
2783         md= decompose_menu_string(but->str);
2784         for (i=0; i<md->nitems; i++)
2785                 if (md->items[i].retval==value)
2786                         strcpy(but->drawstr, md->items[i].str);
2787         menudata_free(md);
2788 }
2789
2790 static void ui_warp_pointer(short x, short y)
2791 {
2792         /* OSX has very poor mousewarp support, it sends events;
2793            this causes a menu being pressed immediately ... */
2794         #ifndef __APPLE__
2795         warp_pointer(x, y);
2796         #endif
2797 }
2798
2799 static int ui_do_but_MENU(uiBut *but)
2800 {
2801         uiBlock *block;
2802         ListBase listb={NULL, NULL};
2803         double fvalue;
2804         int width, height, a, xmax, ymax, starty, endx, endy;
2805         short startx;
2806         int columns=1, rows=0, boxh, event;
2807         short  x1, y1;
2808         short mval[2], mousemove[2];
2809         MenuData *md;
2810
2811         but->flag |= UI_SELECT;
2812         ui_draw_but(but);
2813
2814         block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
2815         block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
2816         uiBlockSetCol(block, MENUCOL);
2817         
2818         md= decompose_menu_string(but->str);
2819
2820         /* columns and row calculation */
2821         columns= (md->nitems+20)/20;
2822         if (columns<1) columns= 1;
2823         
2824         rows= (int) md->nitems/columns;
2825         if (rows<1) rows= 1;
2826         
2827         while (rows*columns<md->nitems) rows++;
2828                 
2829         /* size and location */
2830         if(md->title)
2831                 width= 2*strlen(md->title)+BIF_GetStringWidth(block->curfont, md->title, (U.transopts & TR_MENUS));
2832         else
2833                 width= 0;
2834
2835         for(a=0; a<md->nitems; a++) {
2836                 xmax= BIF_GetStringWidth(block->curfont, md->items[a].str, (U.transopts & TR_MENUS));
2837                 if(xmax>width) width= xmax;
2838         }
2839
2840         width+= 10;
2841         if (width<50) width=50;
2842
2843         boxh= TBOXH;
2844         
2845         height= rows*boxh;
2846         if (md->title) height+= boxh;
2847         
2848         xmax = G.curscreen->sizex;
2849         ymax = G.curscreen->sizey;
2850
2851         getmouseco_sc(mval);
2852         
2853         /* find active item */
2854         fvalue= ui_get_but_val(but);
2855         for(a=0; a<md->nitems; a++) {
2856                 if( md->items[a].retval== (int)fvalue ) break;
2857         }
2858         /* no active item? */
2859         if(a==md->nitems) {
2860                 if(md->title) a= -1;
2861                 else a= 0;
2862         }
2863
2864         if(a>0) startx = mval[0]-width/2 - ((int)(a)/rows)*width;
2865         else startx= mval[0]-width/2;
2866         starty = mval[1]-height + boxh/2 + ((a)%rows)*boxh;
2867
2868         if (md->title) starty+= boxh;
2869         
2870         mousemove[0]= mousemove[1]= 0;
2871         
2872         if(startx<10) {
2873                 mousemove[0]= 10-startx;
2874                 startx= 10;
2875         }
2876         if(starty<10) {
2877                 mousemove[1]= 10-starty;
2878                 starty= 10;
2879         }
2880         
2881         endx= startx+width*columns;
2882         endy= starty+height;
2883         
2884         if(endx>xmax) {
2885                 mousemove[0]= xmax-endx-10;
2886                 endx= xmax-10;
2887                 startx= endx-width*columns;
2888         }
2889         if(endy>ymax) {
2890                 mousemove[1]= ymax-endy-10;
2891                 endy= ymax-10;
2892                 starty= endy-height;
2893         }
2894
2895         ui_warp_pointer(mval[0]+mousemove[0], mval[1]+mousemove[1]);
2896
2897         mousemove[0]= mval[0];
2898         mousemove[1]= mval[1];
2899
2900         /* here we go! */
2901
2902         if(md->title) {
2903                 uiBut *bt;
2904                 uiSetCurFont(block, block->font+1);
2905                 bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+rows*boxh), (short)width, (short)boxh, NULL, 0.0, 0.0, 0, 0, "");
2906                 uiSetCurFont(block, block->font);
2907                 bt->flag= UI_TEXT_LEFT;
2908         }
2909
2910         for(a=0; a<md->nitems; a++) {
2911
2912                 x1= startx + width*((int)a/rows);
2913                 y1= starty - boxh*(a%rows) + (rows-1)*boxh; 
2914
2915                 if (strcmp(md->items[a].str, "%l")==0) {
2916                         uiDefBut(block, SEPR, B_NOP, "", x1, y1,(short)(width-(rows>1)), (short)(boxh-1), NULL, 0.0, 0.0, 0, 0, "");
2917                 }
2918                 else {
2919                         uiDefBut(block, BUTM|but->pointype, but->retval, md->items[a].str, x1, y1,(short)(width-(rows>1)), (short)(boxh-1), but->poin, (float) md->items[a].retval, 0.0, 0, 0, "");
2920                 }
2921         }
2922         
2923         uiBoundsBlock(block, 3);
2924
2925         event= uiDoBlocks(&listb, 0);
2926         
2927         menudata_free(md);
2928         
2929         if((event & UI_RETURN_OUT)==0) ui_warp_pointer(mousemove[0], mousemove[1]);
2930         
2931         but->flag &= ~UI_SELECT;
2932         ui_check_but(but);
2933         ui_draw_but(but);
2934         
2935         uibut_do_func(but);
2936
2937         return event;   
2938 }
2939
2940 /* ************* EVENTS ************* */
2941
2942 void uiGetMouse(int win, short *adr)
2943 {
2944         int x, y;
2945         float xwin, ywin;
2946         
2947         getmouseco_sc(adr);
2948         if (win == G.curscreen->mainwin) return;
2949         
2950         bwin_getsuborigin(win, &x, &y);
2951
2952         adr[0]-= x;
2953         adr[1]-= y;
2954
2955         xwin= adr[0];
2956         ywin= adr[1];
2957
2958         ui_window_to_graphics(win, &xwin, &ywin);
2959
2960         adr[0]= (short)(xwin+0.5);
2961         adr[1]= (short)(ywin+0.5);
2962 }
2963
2964 static void ui_is_but_sel(uiBut *but)
2965 {
2966         double value;
2967         int lvalue;
2968         short push=0, true=1;
2969
2970         value= ui_get_but_val(but);
2971
2972         if( but->type==TOGN ) true= 0;
2973
2974         if( but->bit ) {
2975                 lvalue= (int)value;
2976                 if( BTST(lvalue, (but->bitnr)) ) push= true;
2977                 else push= !true;
2978         }
2979         else {
2980                 switch(but->type) {
2981                 case BUT:
2982                         push= 0;
2983                         break;
2984                 case KEYEVT:
2985                         if (value==-1) push= 1;
2986                         break;
2987                 case TOG:
2988                 case TOGR:
2989                 case TOG3:
2990                 case ICONTOG:
2991                         if(value!=0.0) push= 1;
2992                         break;
2993                 case TOGN:
2994                         if(value==0.0) push= 1;
2995                         break;
2996                 case ROW:
2997                         if(value == but->max) push= 1;
2998                         break;
2999                 case COL:
3000                         push= 1;
3001                         break;
3002                 default:
3003                         push= 2;
3004                         break;
3005                 }
3006         }
3007         
3008         if(push==2);
3009         else if(push==1) but->flag |= UI_SELECT;
3010         else but->flag &= ~UI_SELECT;
3011 }
3012
3013 static int ui_do_but_BUT(uiBut *but)
3014 {
3015         int activated;
3016         
3017         do {
3018                 int oflag= but->flag;
3019                 short mval[2];
3020                         
3021                 uiGetMouse(mywinget(), mval);
3022
3023                 if (uibut_contains_pt(but, mval))
3024                         but->flag |= UI_SELECT;
3025                 else
3026                         but->flag &= ~UI_SELECT;
3027
3028                 if (but->flag != oflag) {
3029                         ui_draw_but(but);
3030                         glFinish(); // flush display in subloops
3031                 }
3032                 
3033                 PIL_sleep_ms(10);
3034         } while (get_mbut() & L_MOUSE);
3035
3036         activated= (but->flag & UI_SELECT);
3037
3038         if(activated) {
3039                 uibut_do_func(but);
3040         }
3041         
3042         but->flag &= ~UI_SELECT;
3043         ui_draw_but(but);
3044
3045         return activated?but->retval:0;
3046 }
3047
3048 static int ui_do_but_KEYEVT(uiBut *but)
3049 {
3050         unsigned short event= 0;
3051         short val;
3052
3053                 /* flag for ui_check_but */
3054         ui_set_but_val(but, -1);
3055         ui_check_but(but);
3056         ui_draw_but(but);
3057
3058         do {
3059                 event= extern_qread(&val);
3060         } while (!event || !val || ELEM(event, MOUSEX, MOUSEY));
3061
3062         if (!key_event_to_string(event)[0]) event= 0;
3063
3064         ui_set_but_val(but, (double) event);
3065         ui_check_but(but);
3066         ui_draw_but(but);
3067         
3068         return (event!=0);
3069 }
3070
3071 static int ui_do_but_TOG(uiBlock *block, uiBut *but)
3072 {
3073         uiBut *bt;
3074         double value;
3075         int w, lvalue, push;
3076         
3077         value= ui_get_but_val(but);
3078         lvalue= (int)value;
3079         
3080         if(but->bit) {
3081                 w= BTST(lvalue, but->bitnr);
3082                 if(w) lvalue = BCLR(lvalue, but->bitnr);
3083                 else lvalue = BSET(lvalue, but->bitnr);
3084                 
3085                 if(but->type==TOGR) {
3086                         if( (get_qual() & LR_SHIFTKEY)==0 ) {
3087                                 lvalue= 1<<(but->bitnr);
3088         
3089                                 ui_set_but_val(but, (double)lvalue);
3090
3091                                 bt= block->buttons.first;
3092                                 while(bt) {
3093                                         if( bt!=but && bt->poin==but->poin ) {
3094                                                 ui_is_but_sel(bt);
3095                                                 ui_draw_but(bt);
3096                                         }
3097                                         bt= bt->next;
3098                                 }
3099                         }
3100                         else {
3101                                 if(lvalue==0) lvalue= 1<<(but->bitnr);
3102                         }
3103                 }
3104                 ui_set_but_val(but, (double)lvalue);
3105                 if(but->type==ICONTOG) ui_check_but(but);
3106                 ui_draw_but(but);
3107         }
3108         else {
3109                 
3110                 if(value==0.0) push= 1; 
3111                 else push= 0;
3112                 
3113                 if(but->type==TOGN) push= !push;
3114                 ui_set_but_val(but, (double)push);
3115                 if(but->type==ICONTOG) ui_check_but(but);               
3116                 ui_draw_but(but);
3117         }
3118         
3119         /* no while loop...this button is used for viewmove */
3120
3121         uibut_do_func(but);
3122
3123         return but->retval;
3124 }
3125
3126 static int ui_do_but_ROW(uiBlock *block, uiBut *but)
3127 {
3128         uiBut *bt;
3129         
3130         ui_set_but_val(but, but->max);
3131         ui_draw_but(but);
3132
3133         bt= block->buttons.first;
3134         while(bt) {
3135                 if( bt!=but && bt->type==ROW ) {
3136                         if(bt->min==but->min) {
3137                                 ui_is_but_sel(bt);
3138                                 ui_draw_but(bt);
3139                         }
3140                 }
3141                 bt= bt->next;
3142         }
3143         return but->retval;
3144 }
3145
3146 static int ui_do_but_TEX(uiBut *but)
3147 {
3148         unsigned short dev;
3149         short x, mval[2], len=0, dodraw;
3150         char *str, backstr[UI_MAX_DRAW_STR];
3151         
3152         str= (char *)but->poin;
3153         
3154         but->flag |= UI_SELECT;
3155
3156         uiGetMouse(mywinget(), mval);
3157
3158         /* calculate cursor pos with current mousecoords */
3159         BLI_strncpy(backstr, but->drawstr, UI_MAX_DRAW_STR);
3160         but->pos= strlen(backstr)-but->ofs;
3161
3162         while((but->aspect*BIF_GetStringWidth(but->font, backstr+but->ofs, (U.transopts & TR_BUTTONS)) + but->x1) > mval[0]) {
3163                 if (but->pos <= 0) break;
3164                 but->pos--;
3165                 backstr[but->pos+but->ofs] = 0;
3166         }
3167         
3168         but->pos -= strlen(but->str);
3169         but->pos += but->ofs;
3170         if(but->pos<0) but->pos= 0;
3171
3172         /* backup */
3173         BLI_strncpy(backstr, but->poin, UI_MAX_DRAW_STR);
3174
3175         ui_draw_but(but);
3176         glFinish(); // flush display in subloops
3177         
3178         while (get_mbut() & L_MOUSE) BIF_wait_for_statechange();
3179         len= strlen(str);
3180         but->min= 0.0;
3181         
3182         while(TRUE) {
3183                 char ascii;
3184                 short val;
3185
3186                 dodraw= 0;
3187                 dev = extern_qread_ext(&val, &ascii);
3188
3189                 if(dev==INPUTCHANGE) break;
3190                 else if(get_mbut() & L_MOUSE) break;
3191                 else if(get_mbut() & R_MOUSE) break;
3192                 else if(dev==ESCKEY) break;
3193                 else if(dev==MOUSEX) val= 0;
3194                 else if(dev==MOUSEY) val= 0;
3195
3196                 if(ascii) {
3197                         if( ascii>31 && ascii<127) {
3198                                 if(len < but->max) {
3199                                         for(x= but->max; x>but->pos; x--)
3200                                                 str[x]= str[x-1];
3201                                         str[but->pos]= ascii;
3202                                         but->pos++; 
3203                                         len++;
3204                                         str[len]= '\0';
3205                                         dodraw= 1;
3206                                 }
3207                         }
3208                 }
3209                 else if(val) {
3210                 
3211                         if(dev==RIGHTARROWKEY) {
3212                                 if(G.qual & LR_SHIFTKEY) but->pos= strlen(str);
3213                                 else but->pos++;
3214                                 if(but->pos>strlen(str)) but->pos= strlen(str);
3215                                 dodraw= 1;
3216                         }
3217                         else if(dev==LEFTARROWKEY) {
3218                                 if(G.qual & LR_SHIFTKEY) but->pos= 0;
3219                                 else if(but->pos>0) but->pos--;
3220                                 dodraw= 1;
3221                         }
3222                         else if(dev==PADENTER || dev==RETKEY) {
3223                                 break;
3224                         }
3225                         else if(dev==DELKEY) {
3226                                         if(but->pos>=0 && but->pos<strlen(str)) {
3227                                                         for(x=but->pos; x<=strlen(str); x++)
3228                                                                         str[x]= str[x+1];
3229                                                         str[--len]='\0';
3230                                                         dodraw= 1;
3231                                         }
3232                         }
3233                         else if(dev==BACKSPACEKEY) {
3234                                 if(len!=0) {
3235                                         if(get_qual() & LR_SHIFTKEY) {
3236                                                 str[0]= 0;
3237                                                 but->pos= 0;
3238                                                 len= 0;
3239                                                 dodraw= 1;
3240                                         }
3241                                         else if(but->pos>0) {
3242                                                 for(x=but->pos; x<=strlen(str); x++)
3243                                                         str[x-1]= str[x];
3244                                                 but->pos--;
3245                                                 str[--len]='\0';
3246                                                 dodraw= 1;
3247                                         }
3248                                 } 
3249                         }
3250                 }
3251                 if(dodraw) {
3252                         ui_check_but(but);
3253                         ui_draw_but(but);
3254                         glFinish(); // flush display in subloops
3255                 }
3256         }
3257         
3258         if(dev==ESCKEY) strcpy(but->poin, backstr);
3259         but->pos= -1;
3260         but->flag &= ~UI_SELECT;
3261
3262         uibut_do_func(but);
3263
3264         ui_check_but(but);
3265         ui_draw_but(but);
3266         
3267         if(dev!=ESCKEY) return but->retval;
3268         else return 0;
3269 }
3270
3271
3272 static int uiActAsTextBut(uiBut *but)
3273 {
3274         double value;
3275         float min, max;
3276         int temp, retval, textleft;
3277         char str[UI_MAX_DRAW_STR], *point;
3278         
3279         
3280         value= ui_get_but_val(but);
3281         if( but->pointype==FLO ) {
3282                 if(but->a2) { /* amount of digits defined */
3283                         if(but->a2==1) sprintf(str, "%.1f", value);
3284                         else if(but->a2==2) sprintf(str, "%.2f", value);
3285                         else if(but->a2==3) sprintf(str, "%.3f", value);
3286                         else sprintf(str, "%.4f", value);
3287                 }
3288                 else sprintf(str, "%.3f", value);
3289         }
3290         else {
3291                 sprintf(str, "%d", (int)value);
3292         }
3293         point= but->poin;
3294         but->poin= str;
3295         min= but->min;
3296         max= but->max;
3297         but->min= 0.0;
3298         but->max= 15.0;
3299         temp= but->type;
3300         but->type= TEX;
3301         textleft= but->flag & UI_TEXT_LEFT;
3302         but->flag |= UI_TEXT_LEFT;
3303         ui_check_but(but);
3304         
3305         retval= ui_do_but_TEX(but);
3306         
3307         but->type= temp;
3308         but->poin= point;
3309         but->min= min;
3310         but->max= max;
3311         if(textleft==0) but->flag &= ~UI_TEXT_LEFT;
3312
3313         if( but->pointype==FLO ) value= atof(str);
3314         else value= atoi(str);
3315
3316         if(value<min) value= min;
3317         if(value>max) value= max;
3318
3319         ui_set_but_val(but, value);
3320         ui_check_but(but);
3321         ui_draw_but(but);
3322         
3323         return retval;
3324 }
3325
3326 static int ui_do_but_NUM(uiBut *but)
3327 {
3328         double value;
3329         float deler, fstart, f, tempf;
3330         int lvalue, temp; /*  , firsttime=1; */
3331         short qual, sx, mval[2], pos=0;
3332         
3333
3334         but->flag |= UI_SELECT;
3335         ui_draw_but(but);
3336         glFinish(); // flush display before subloop
3337         
3338         uiGetMouse(mywinget(), mval);
3339         value= ui_get_but_val(but);
3340         
3341         sx= mval[0];
3342         fstart= (value - but->min)/(but->max-but->min);
3343         f= fstart;
3344         
3345         temp= (int)value;
3346         tempf= value;
3347         
3348         if(get_qual() & LR_SHIFTKEY) {  /* make it textbut */
3349                 if( uiActAsTextBut(but) ) return but->retval;
3350                 else return 0;
3351         }
3352         
3353         /* firsttime: this button can be approached with enter as well */
3354         while (get_mbut() & L_MOUSE) {
3355                 qual= get_qual();
3356                 
3357                 deler= 500;
3358                 if( but->pointype!=FLO ) {
3359
3360                         if( (but->max-but->min)<100 ) deler= 200.0;
3361                         if( (but->max-but->min)<25 ) deler= 50.0;
3362
3363                 }
3364                 if(qual & LR_SHIFTKEY) deler*= 10.0;
3365                 if(qual & LR_ALTKEY) deler*= 20.0;
3366
3367                 uiGetMouse(mywinget(), mval);
3368                 
3369                 if(mval[0] != sx) {
3370                 
3371                         f+= ((float)(mval[0]-sx))/deler;
3372                         if(f>1.0) f= 1.0;
3373                         if(f<0.0) f= 0.0;
3374                         sx= mval[0];
3375                         tempf= ( but->min + f*(but->max-but->min));
3376                         
3377                         if( but->pointype!=FLO ) {
3378                                 
3379                                 temp= floor(tempf+.5);
3380                                 
3381                                 if(tempf==but->min || tempf==but->max);
3382                                 else if(qual & LR_CTRLKEY) temp= 10*(temp/10);
3383                                 
3384                                 if( temp>=but->min && temp<=but->max) {
3385                                 
3386                                         value= ui_get_but_val(but);
3387                                         lvalue= (int)value;
3388                                         
3389                                         if(temp != lvalue ) {
3390                                                 pos= 1;
3391                                                 ui_set_but_val(but, (double)temp);
3392                                                 ui_check_but(but);
3393                                                 ui_draw_but(but);
3394                                                 glFinish(); // flush display in subloops
3395                                                 
3396                                                 uibut_do_func(but);
3397                                         }
3398                                 }
3399
3400                         }
3401                         else {
3402                                 temp= 0;
3403                                 if(qual & LR_CTRLKEY) {
3404                                         if(tempf==but->min || tempf==but->max);
3405                                         else if(but->max-but->min < 2.10) tempf= 0.1*floor(10*tempf);
3406                                         else if(but->max-but->min < 21.0) tempf= floor(tempf);
3407                                         else tempf= 10.0*floor(tempf/10.0);
3408                                 }
3409
3410                                 if( tempf>=but->min && tempf<=but->max) {
3411                                         value= ui_get_but_val(but);
3412                                         
3413                                         if(tempf != value ) {
3414                                                 pos= 1;
3415                                                 ui_set_but_val(but, tempf);
3416                                                 ui_check_but(but);
3417                                                 ui_draw_but(but);
3418                                                 glFinish(); // flush display in subloops
3419                                         }
3420                                 }
3421
3422                         }
3423                 }
3424                 BIF_wait_for_statechange();
3425         }
3426         
3427         if(pos==0) {  /* plus 1 or minus 1 */
3428                 if( but->pointype!=FLO ) {
3429
3430                         if(sx<(but->x1+but->x2)/2) temp--;
3431                         else temp++;
3432                         
3433                         if( temp>=but->min && temp<=but->max)
3434                                 ui_set_but_val(but, (double)temp);
3435
3436                 }
3437                 else {
3438                 
3439                         if(sx<(but->x1+but->x2)/2) tempf-= 0.01*but->a1;
3440                                 else tempf+= 0.01*but->a1;
3441
3442                         if (tempf < but->min) tempf = but->min;
3443                         if (tempf > but->max) tempf = but->max;
3444
3445                         ui_set_but_val(but, tempf);
3446
3447                 }
3448         }
3449         
3450         but->flag &= ~UI_SELECT;
3451         ui_check_but(but);
3452         ui_draw_but(but);       
3453         glFinish(); // flush display in subloops
3454         
3455         return but->retval;
3456 }
3457
3458 static int ui_do_but_TOG3(uiBut *but)
3459
3460
3461         if( but->pointype==SHO ) {
3462                 short *sp= (short *)but->poin;
3463                 
3464                 if( BTST(sp[1], but->bitnr)) {
3465                         sp[1]= BCLR(sp[1], but->bitnr);
3466                         sp[0]= BCLR(sp[0], but->bitnr);
3467                 }
3468                 else if( BTST(sp[0], but->bitnr)) {
3469                         sp[1]= BSET(sp[1], but->bitnr);
3470                 } else {
3471                         sp[0]= BSET(sp[0], but->bitnr);
3472                 }
3473         }
3474         else {
3475                 if( BTST(*(but->poin+2), but->bitnr)) {
3476                         *(but->poin+2)= BCLR(*(but->poin+2), but->bitnr);
3477                         *(but->poin)= BCLR(*(but->poin), but->bitnr);
3478                 }
3479                 else if( BTST(*(but->poin), but->bitnr)) {
3480                         *(but->poin+2)= BSET(*(but->poin+2), but->bitnr);
3481                 } else {
3482                         *(but->poin)= BSET(*(but->poin), but->bitnr);
3483                 }
3484         }
3485         
3486         ui_is_but_sel(but);
3487         ui_draw_but(but);
3488         
3489         return but->retval;
3490 }
3491
3492 static int ui_do_but_ICONROW(uiBut *but)
3493 {
3494         ListBase listb= {NULL, NULL};
3495         uiBlock *block;
3496         int a;
3497         
3498         but->flag |= UI_SELECT;
3499         ui_draw_but(but);
3500         
3501         /* here we go! */
3502         block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, but->win);
3503         block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
3504         uiBlockSetCol(block, MENUCOL);
3505         
3506         for(a=(int)but->min; a<=(int)but->max; a++) {
3507                 uiDefIconBut(block, BUTM|but->pointype, but->retval, but->icon+(a-but->min), 0, (short)(18*a), (short)(but->x2-but->x1-4), 18, but->poin, (float)a, 0.0, 0, 0, "");
3508         }
3509         block->direction= UI_TOP;       
3510         ui_positionblock(block, but);
3511         
3512         /* the block is made with but-win, but is handled in mainwin space...
3513            this is needs better implementation */
3514         block->win= G.curscreen->mainwin;
3515         
3516         uiDoBlocks(&listb, 0);
3517
3518         but->flag &= ~UI_SELECT;
3519         ui_check_but(but);
3520         ui_draw_but(but);       
3521         
3522         return but->retval;
3523 }
3524
3525 static int ui_do_but_ICONTEXTROW(uiBut *but)
3526 {
3527         uiBlock *block;
3528         ListBase listb={NULL, NULL};
3529         int width, a, xmax, ypos;
3530         MenuData *md;
3531
3532         but->flag |= UI_SELECT;
3533         ui_draw_but(but);
3534
3535         block= uiNewBlock(&listb, "menu", UI_EMBOSSP, UI_HELV, but->win);
3536         block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
3537         uiBlockSetCol(block, MENUCOL);
3538         md= decompose_menu_string(but->str);
3539
3540         /* size and location */
3541         /* expand menu width to fit labels */
3542         if(md->title)
3543                 width= 2*strlen(md->title)+BIF_GetStringWidth(block->curfont, md->title, (U.transopts & TR_MENUS));
3544         else
3545                 width= 0;
3546
3547         for(a=0; a<md->nitems; a++) {
3548                 xmax= BIF_GetStringWidth(block->curfont, md->items[a].str, (U.transopts & TR_MENUS));
3549                 if(xmax>width) width= xmax;
3550         }
3551
3552         width+= 30;
3553         if (width<50) width=50;
3554
3555         ypos = 0;
3556