39e362ef85a3698d5e21e8522610292d123968c9
[blender-staging.git] / source / blender / editors / interface / interface_draw.c
1 /**
2  * $Id: interface_draw.c 15733 2008-07-24 09:23:13Z aligorith $
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <math.h>
31 #include <string.h>
32
33 #include "DNA_color_types.h"
34 #include "DNA_listBase.h"
35 #include "DNA_object_types.h"
36 #include "DNA_screen_types.h"
37 #include "DNA_texture_types.h"
38 #include "DNA_userdef_types.h"
39
40 #include "BLI_arithb.h"
41
42 #include "BKE_colortools.h"
43 #include "BKE_texture.h"
44 #include "BKE_utildefines.h"
45
46 #include "BIF_gl.h"
47 #include "BIF_glutil.h"
48
49 #include "UI_interface.h"
50 #include "UI_interface_icons.h"
51 #include "UI_text.h"
52
53 #include "BMF_Api.h"
54 #ifdef INTERNATIONAL
55 #include "FTF_Api.h"
56 #endif
57
58 #include "interface_intern.h"
59
60 #define UI_RB_ALPHA 16
61 static int roundboxtype= 15;
62
63 void uiSetRoundBox(int type)
64 {
65         /* Not sure the roundbox function is the best place to change this
66          * if this is undone, its not that big a deal, only makes curves edges
67          * square for the  */
68         if (UI_GetThemeValue(TH_BUT_DRAWTYPE) == TH_MINIMAL)
69                 roundboxtype= 0;
70         else
71                 roundboxtype= type;
72
73         /* flags to set which corners will become rounded:
74
75         1------2
76         |      |
77         8------4
78         */
79         
80 }
81
82 void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad)
83 {
84         float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
85                           {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
86         int a;
87         
88         /* mult */
89         for(a=0; a<7; a++) {
90                 vec[a][0]*= rad; vec[a][1]*= rad;
91         }
92
93         glBegin(mode);
94
95         /* start with corner right-bottom */
96         if(roundboxtype & 4) {
97                 glVertex2f(maxx-rad, miny);
98                 for(a=0; a<7; a++) {
99                         glVertex2f(maxx-rad+vec[a][0], miny+vec[a][1]);
100                 }
101                 glVertex2f(maxx, miny+rad);
102         }
103         else glVertex2f(maxx, miny);
104         
105         /* corner right-top */
106         if(roundboxtype & 2) {
107                 glVertex2f(maxx, maxy-rad);
108                 for(a=0; a<7; a++) {
109                         glVertex2f(maxx-vec[a][1], maxy-rad+vec[a][0]);
110                 }
111                 glVertex2f(maxx-rad, maxy);
112         }
113         else glVertex2f(maxx, maxy);
114         
115         /* corner left-top */
116         if(roundboxtype & 1) {
117                 glVertex2f(minx+rad, maxy);
118                 for(a=0; a<7; a++) {
119                         glVertex2f(minx+rad-vec[a][0], maxy-vec[a][1]);
120                 }
121                 glVertex2f(minx, maxy-rad);
122         }
123         else glVertex2f(minx, maxy);
124         
125         /* corner left-bottom */
126         if(roundboxtype & 8) {
127                 glVertex2f(minx, miny+rad);
128                 for(a=0; a<7; a++) {
129                         glVertex2f(minx+vec[a][1], miny+rad-vec[a][0]);
130                 }
131                 glVertex2f(minx+rad, miny);
132         }
133         else glVertex2f(minx, miny);
134         
135         glEnd();
136 }
137
138 static void round_box_shade_col(float *col1, float *col2, float fac)
139 {
140         float col[3];
141
142         col[0]= (fac*col1[0] + (1.0-fac)*col2[0]);
143         col[1]= (fac*col1[1] + (1.0-fac)*col2[1]);
144         col[2]= (fac*col1[2] + (1.0-fac)*col2[2]);
145         
146         glColor3fv(col);
147 }
148
149 /* only for headers */
150 static void gl_round_box_topshade(float minx, float miny, float maxx, float maxy, float rad)
151 {
152         float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
153                           {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
154         char col[7]= {140, 165, 195, 210, 230, 245, 255};
155         int a;
156         char alpha=255;
157         
158         if(roundboxtype & UI_RB_ALPHA) alpha= 128;
159         
160         /* mult */
161         for(a=0; a<7; a++) {
162                 vec[a][0]*= rad; vec[a][1]*= rad;
163         }
164
165         /* shades from grey->white->grey */
166         glBegin(GL_LINE_STRIP);
167         
168         if(roundboxtype & 3) {
169                 /* corner right-top */
170                 glColor4ub(140, 140, 140, alpha);
171                 glVertex2f( maxx, maxy-rad);
172                 for(a=0; a<7; a++) {
173                         glColor4ub(col[a], col[a], col[a], alpha);
174                         glVertex2f( maxx-vec[a][1], maxy-rad+vec[a][0]);
175                 }
176                 glColor4ub(225, 225, 225, alpha);
177                 glVertex2f( maxx-rad, maxy);
178         
179                 
180                 /* corner left-top */
181                 glVertex2f( minx+rad, maxy);
182                 for(a=0; a<7; a++) {
183                         glColor4ub(col[6-a], col[6-a], col[6-a], alpha);
184                         glVertex2f( minx+rad-vec[a][0], maxy-vec[a][1]);
185                 }
186                 glVertex2f( minx, maxy-rad);
187         }
188         else {
189                 glColor4ub(225, 225, 225, alpha);
190                 glVertex2f( minx, maxy);
191                 glVertex2f( maxx, maxy);
192         }
193         
194         glEnd();
195 }
196
197 /* linear horizontal shade within button or in outline */
198 void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown)
199 {
200         float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
201                           {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
202         float div= maxy-miny;
203         float coltop[3], coldown[3], color[4];
204         int a;
205         
206         /* mult */
207         for(a=0; a<7; a++) {
208                 vec[a][0]*= rad; vec[a][1]*= rad;
209         }
210         /* get current color, needs to be outside of glBegin/End */
211         glGetFloatv(GL_CURRENT_COLOR, color);
212
213         /* 'shade' defines strength of shading */       
214         coltop[0]= color[0]+shadetop; if(coltop[0]>1.0) coltop[0]= 1.0;
215         coltop[1]= color[1]+shadetop; if(coltop[1]>1.0) coltop[1]= 1.0;
216         coltop[2]= color[2]+shadetop; if(coltop[2]>1.0) coltop[2]= 1.0;
217         coldown[0]= color[0]+shadedown; if(coldown[0]<0.0) coldown[0]= 0.0;
218         coldown[1]= color[1]+shadedown; if(coldown[1]<0.0) coldown[1]= 0.0;
219         coldown[2]= color[2]+shadedown; if(coldown[2]<0.0) coldown[2]= 0.0;
220
221         if (UI_GetThemeValue(TH_BUT_DRAWTYPE) != TH_MINIMAL) {
222                 glShadeModel(GL_SMOOTH);
223                 glBegin(mode);
224         }
225
226         /* start with corner right-bottom */
227         if(roundboxtype & 4) {
228                 
229                 round_box_shade_col(coltop, coldown, 0.0);
230                 glVertex2f(maxx-rad, miny);
231                 
232                 for(a=0; a<7; a++) {
233                         round_box_shade_col(coltop, coldown, vec[a][1]/div);
234                         glVertex2f(maxx-rad+vec[a][0], miny+vec[a][1]);
235                 }
236                 
237                 round_box_shade_col(coltop, coldown, rad/div);
238                 glVertex2f(maxx, miny+rad);
239         }
240         else {
241                 round_box_shade_col(coltop, coldown, 0.0);
242                 glVertex2f(maxx, miny);
243         }
244         
245         /* corner right-top */
246         if(roundboxtype & 2) {
247                 
248                 round_box_shade_col(coltop, coldown, (div-rad)/div);
249                 glVertex2f(maxx, maxy-rad);
250                 
251                 for(a=0; a<7; a++) {
252                         round_box_shade_col(coltop, coldown, (div-rad+vec[a][1])/div);
253                         glVertex2f(maxx-vec[a][1], maxy-rad+vec[a][0]);
254                 }
255                 round_box_shade_col(coltop, coldown, 1.0);
256                 glVertex2f(maxx-rad, maxy);
257         }
258         else {
259                 round_box_shade_col(coltop, coldown, 1.0);
260                 glVertex2f(maxx, maxy);
261         }
262         
263         /* corner left-top */
264         if(roundboxtype & 1) {
265                 
266                 round_box_shade_col(coltop, coldown, 1.0);
267                 glVertex2f(minx+rad, maxy);
268                 
269                 for(a=0; a<7; a++) {
270                         round_box_shade_col(coltop, coldown, (div-vec[a][1])/div);
271                         glVertex2f(minx+rad-vec[a][0], maxy-vec[a][1]);
272                 }
273                 
274                 round_box_shade_col(coltop, coldown, (div-rad)/div);
275                 glVertex2f(minx, maxy-rad);
276         }
277         else {
278                 round_box_shade_col(coltop, coldown, 1.0);
279                 glVertex2f(minx, maxy);
280         }
281         
282         /* corner left-bottom */
283         if(roundboxtype & 8) {
284                 
285                 round_box_shade_col(coltop, coldown, rad/div);
286                 glVertex2f(minx, miny+rad);
287                 
288                 for(a=0; a<7; a++) {
289                         round_box_shade_col(coltop, coldown, (rad-vec[a][1])/div);
290                         glVertex2f(minx+vec[a][1], miny+rad-vec[a][0]);
291                 }
292                 
293                 round_box_shade_col(coltop, coldown, 0.0);
294                 glVertex2f(minx+rad, miny);
295         }
296         else {
297                 round_box_shade_col(coltop, coldown, 0.0);
298                 glVertex2f(minx, miny);
299         }
300         
301         glEnd();
302         glShadeModel(GL_FLAT);
303 }
304
305 /* linear vertical shade within button or in outline */
306 void gl_round_box_vertical_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight)
307 {
308         float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
309                           {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
310         float div= maxx-minx;
311         float colLeft[3], colRight[3], color[4];
312         int a;
313         
314         /* mult */
315         for(a=0; a<7; a++) {
316                 vec[a][0]*= rad; vec[a][1]*= rad;
317         }
318         /* get current color, needs to be outside of glBegin/End */
319         glGetFloatv(GL_CURRENT_COLOR, color);
320
321         /* 'shade' defines strength of shading */       
322         colLeft[0]= color[0]+shadeLeft; if(colLeft[0]>1.0) colLeft[0]= 1.0;
323         colLeft[1]= color[1]+shadeLeft; if(colLeft[1]>1.0) colLeft[1]= 1.0;
324         colLeft[2]= color[2]+shadeLeft; if(colLeft[2]>1.0) colLeft[2]= 1.0;
325         colRight[0]= color[0]+shadeRight; if(colRight[0]<0.0) colRight[0]= 0.0;
326         colRight[1]= color[1]+shadeRight; if(colRight[1]<0.0) colRight[1]= 0.0;
327         colRight[2]= color[2]+shadeRight; if(colRight[2]<0.0) colRight[2]= 0.0;
328
329         if (UI_GetThemeValue(TH_BUT_DRAWTYPE) != TH_MINIMAL) {
330                 glShadeModel(GL_SMOOTH);
331                 glBegin(mode);
332         }
333
334         /* start with corner right-bottom */
335         if(roundboxtype & 4) {
336                 round_box_shade_col(colLeft, colRight, 0.0);
337                 glVertex2f(maxx-rad, miny);
338                 
339                 for(a=0; a<7; a++) {
340                         round_box_shade_col(colLeft, colRight, vec[a][0]/div);
341                         glVertex2f(maxx-rad+vec[a][0], miny+vec[a][1]);
342                 }
343                 
344                 round_box_shade_col(colLeft, colRight, rad/div);
345                 glVertex2f(maxx, miny+rad);
346         }
347         else {
348                 round_box_shade_col(colLeft, colRight, 0.0);
349                 glVertex2f(maxx, miny);
350         }
351         
352         /* corner right-top */
353         if(roundboxtype & 2) {
354                 round_box_shade_col(colLeft, colRight, 0.0);
355                 glVertex2f(maxx, maxy-rad);
356                 
357                 for(a=0; a<7; a++) {
358                         
359                         round_box_shade_col(colLeft, colRight, (div-rad-vec[a][0])/div);
360                         glVertex2f(maxx-vec[a][1], maxy-rad+vec[a][0]);
361                 }
362                 round_box_shade_col(colLeft, colRight, (div-rad)/div);
363                 glVertex2f(maxx-rad, maxy);
364         }
365         else {
366                 round_box_shade_col(colLeft, colRight, 0.0);
367                 glVertex2f(maxx, maxy);
368         }
369         
370         /* corner left-top */
371         if(roundboxtype & 1) {
372                 round_box_shade_col(colLeft, colRight, (div-rad)/div);
373                 glVertex2f(minx+rad, maxy);
374                 
375                 for(a=0; a<7; a++) {
376                         round_box_shade_col(colLeft, colRight, (div-rad+vec[a][0])/div);
377                         glVertex2f(minx+rad-vec[a][0], maxy-vec[a][1]);
378                 }
379                 
380                 round_box_shade_col(colLeft, colRight, 1.0);
381                 glVertex2f(minx, maxy-rad);
382         }
383         else {
384                 round_box_shade_col(colLeft, colRight, 1.0);
385                 glVertex2f(minx, maxy);
386         }
387         
388         /* corner left-bottom */
389         if(roundboxtype & 8) {
390                 round_box_shade_col(colLeft, colRight, 1.0);
391                 glVertex2f(minx, miny+rad);
392                 
393                 for(a=0; a<7; a++) {
394                         round_box_shade_col(colLeft, colRight, (vec[a][0])/div);
395                         glVertex2f(minx+vec[a][1], miny+rad-vec[a][0]);
396                 }
397                 
398                 round_box_shade_col(colLeft, colRight, 1.0);
399                 glVertex2f(minx+rad, miny);
400         }
401         else {
402                 round_box_shade_col(colLeft, colRight, 1.0);
403                 glVertex2f(minx, miny);
404         }
405         
406         glEnd();
407         glShadeModel(GL_FLAT);
408 }
409
410 /* plain antialiased unfilled rectangle */
411 void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad)
412 {
413         float color[4];
414         
415         if(roundboxtype & UI_RB_ALPHA) {
416                 glGetFloatv(GL_CURRENT_COLOR, color);
417                 color[3]= 0.5;
418                 glColor4fv(color);
419                 glEnable( GL_BLEND );
420         }
421         
422         /* set antialias line */
423         if (UI_GetThemeValue(TH_BUT_DRAWTYPE) != TH_MINIMAL) {
424                 glEnable( GL_LINE_SMOOTH );
425                 glEnable( GL_BLEND );
426         }
427
428         gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
429    
430         glDisable( GL_BLEND );
431         glDisable( GL_LINE_SMOOTH );
432 }
433
434 /* plain fake antialiased unfilled round rectangle */
435 void uiRoundRectFakeAA(float minx, float miny, float maxx, float maxy, float rad, float asp)
436 {
437         float color[4];
438         float raddiff;
439         int i, passes=4;
440         
441         /* get the colour and divide up the alpha */
442         glGetFloatv(GL_CURRENT_COLOR, color);
443         color[3]= 1/(float)passes;
444         glColor4fv(color);
445         
446         /* set the 'jitter amount' */
447         raddiff = (1/(float)passes) * asp;
448         
449         glEnable( GL_BLEND );
450         
451         /* draw lots of lines on top of each other */
452         for (i=passes; i>=(-passes); i--) {
453                 gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad+(i*raddiff));
454         }
455         
456         glDisable( GL_BLEND );
457 }
458
459 /* (old, used in outliner) plain antialiased filled box */
460 void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad)
461 {
462         float color[4];
463         
464         if(roundboxtype & UI_RB_ALPHA) {
465                 glGetFloatv(GL_CURRENT_COLOR, color);
466                 color[3]= 0.5;
467                 glColor4fv(color);
468                 glEnable( GL_BLEND );
469         }
470         
471         /* solid part */
472         gl_round_box(GL_POLYGON, minx, miny, maxx, maxy, rad);
473         
474         /* set antialias line */
475         if (UI_GetThemeValue(TH_BUT_DRAWTYPE) != TH_MINIMAL) {
476                 glEnable( GL_LINE_SMOOTH );
477                 glEnable( GL_BLEND );
478         }
479         
480         gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
481         
482         glDisable( GL_BLEND );
483         glDisable( GL_LINE_SMOOTH );
484 }
485
486 void uiTriangleFakeAA(float x1, float y1, float x2, float y2, float x3, float y3)
487 {
488         float color[4];
489         float jitter;
490         int i, passes=4;
491         
492         /* get the colour and divide up the alpha */
493         glGetFloatv(GL_CURRENT_COLOR, color);
494         color[3]= 1/(float)passes;
495         glColor4fv(color);
496         
497         /* set the 'jitter amount' */
498         jitter = 1/(float)passes;
499         
500         glEnable( GL_BLEND );
501         
502         /* draw lots of lines on top of each other */
503         for (i=passes; i>=(-passes); i--) {
504                 glBegin(GL_TRIANGLES);
505                 
506                 /* 'point' first, then two base vertices */
507                 glVertex2f(x1+(i*jitter), y1+(i*jitter));
508                 glVertex2f(x2, y2+(i*jitter));
509                 glVertex2f(x3, y3+(i*jitter));
510                 glEnd();
511         }
512         
513         glDisable( GL_BLEND );
514 }
515
516 /* for headers and floating panels */
517 void uiRoundBoxEmboss(float minx, float miny, float maxx, float maxy, float rad, int active)
518 {
519         float color[4];
520         
521         if(roundboxtype & UI_RB_ALPHA) {
522                 glGetFloatv(GL_CURRENT_COLOR, color);
523                 color[3]= 0.5;
524                 glColor4fv(color);
525                 glEnable( GL_BLEND );
526         }
527         
528         /* solid part */
529         //if(active)
530         //      gl_round_box_shade(GL_POLYGON, minx, miny, maxx, maxy, rad, 0.10, -0.05);
531         // else
532         /* shading doesnt work for certain buttons yet (pulldown) need smarter buffer caching (ton) */
533         gl_round_box(GL_POLYGON, minx, miny, maxx, maxy, rad);
534         
535         /* set antialias line */
536         if (UI_GetThemeValue(TH_BUT_DRAWTYPE) != TH_MINIMAL) {
537                 glEnable( GL_LINE_SMOOTH );
538                 glEnable( GL_BLEND );
539         }
540
541         /* top shade */
542         gl_round_box_topshade(minx+1, miny+1, maxx-1, maxy-1, rad);
543
544         /* total outline */
545         if(roundboxtype & UI_RB_ALPHA) glColor4ub(0,0,0, 128); else glColor4ub(0,0,0, 200);
546         gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
547    
548         glDisable( GL_LINE_SMOOTH );
549
550         /* bottom shade for header down */
551         if((roundboxtype & 12)==12) {
552                 glColor4ub(0,0,0, 80);
553                 fdrawline(minx+rad-1.0, miny+1.0, maxx-rad+1.0, miny+1.0);
554         }
555         glDisable( GL_BLEND );
556 }
557
558 /* plain antialiased filled box */
559 #if 0
560 void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad)
561 {
562         float color[4];
563         
564         if(roundboxtype & UI_RB_ALPHA) {
565                 glGetFloatv(GL_CURRENT_COLOR, color);
566                 color[3]= 0.5;
567                 glColor4fv(color);
568                 glEnable( GL_BLEND );
569         }
570         
571         /* solid part */
572         gl_round_box(GL_POLYGON, minx, miny, maxx, maxy, rad);
573         
574         /* set antialias line */
575         if (UI_GetThemeValue(TH_BUT_DRAWTYPE) != TH_MINIMAL) {
576                 glEnable( GL_LINE_SMOOTH );
577                 glEnable( GL_BLEND );
578         }
579                 
580         gl_round_box(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
581    
582         glDisable( GL_BLEND );
583         glDisable( GL_LINE_SMOOTH );
584 }
585 #endif
586
587
588 /* ************** safe rasterpos for pixmap alignment with pixels ************* */
589
590 void ui_rasterpos_safe(float x, float y, float aspect)
591 {
592         float vals[4], remainder;
593         int doit=0;
594         
595         glRasterPos2f(x, y);
596         glGetFloatv(GL_CURRENT_RASTER_POSITION, vals);
597
598         remainder= vals[0] - floor(vals[0]);
599         if(remainder > 0.4 && remainder < 0.6) {
600                 if(remainder < 0.5) x -= 0.1*aspect;
601                 else x += 0.1*aspect;
602                 doit= 1;
603         }
604         remainder= vals[1] - floor(vals[1]);
605         if(remainder > 0.4 && remainder < 0.6) {
606                 if(remainder < 0.5) y -= 0.1*aspect;
607                 else y += 0.1*aspect;
608                 doit= 1;
609         }
610         
611         if(doit) glRasterPos2f(x, y);
612
613         UI_RasterPos(x, y);
614         UI_SetScale(aspect);
615 }
616
617 /* ************** generic embossed rect, for window sliders etc ************* */
618
619 void uiEmboss(float x1, float y1, float x2, float y2, int sel)
620 {
621         
622         /* below */
623         if(sel) glColor3ub(200,200,200);
624         else glColor3ub(50,50,50);
625         fdrawline(x1, y1, x2, y1);
626
627         /* right */
628         fdrawline(x2, y1, x2, y2);
629         
630         /* top */
631         if(sel) glColor3ub(50,50,50);
632         else glColor3ub(200,200,200);
633         fdrawline(x1, y2, x2, y2);
634
635         /* left */
636         fdrawline(x1, y1, x1, y2);
637         
638 }
639
640 /* ************** GENERIC ICON DRAW, NO THEME HERE ************* */
641
642 /* icons have been standardized... and this call draws in untransformed coordinates */
643 #define ICON_HEIGHT             16.0f
644
645 static void ui_draw_icon(uiBut *but, BIFIconID icon, int blend)
646 {
647         float xs=0, ys=0, aspect, height;
648
649         /* this icon doesn't need draw... */
650         if(icon==ICON_BLANK1) return;
651         
652         /* we need aspect from block, for menus... these buttons are scaled in uiPositionBlock() */
653         aspect= but->block->aspect;
654         if(aspect != but->aspect) {
655                 /* prevent scaling up icon in pupmenu */
656                 if (aspect < 1.0f) {                    
657                         height= ICON_HEIGHT;
658                         aspect = 1.0f;
659                         
660                 }
661                 else 
662                         height= ICON_HEIGHT/aspect;
663         }
664         else
665                 height= ICON_HEIGHT;
666         
667         if(but->flag & UI_ICON_LEFT) {
668                 if (but->type==BUT_TOGDUAL) {
669                         if (but->drawstr[0]) {
670                                 xs= but->x1-1.0;
671                         } else {
672                                 xs= (but->x1+but->x2- height)/2.0;
673                         }
674                 }
675                 else if (but->type==BUTM ) {
676                         xs= but->x1+1.0;
677                 }
678                 else if ((but->type==ICONROW) || (but->type==ICONTEXTROW)) {
679                         xs= but->x1+3.0;
680                 }
681                 else {
682                         xs= but->x1+4.0;
683                 }
684                 ys= (but->y1+but->y2- height)/2.0;
685         }
686         if(but->flag & UI_ICON_RIGHT) {
687                 xs= but->x2-17.0;
688                 ys= (but->y1+but->y2- height)/2.0;
689         }
690         if (!((but->flag & UI_ICON_RIGHT) || (but->flag & UI_ICON_LEFT))) {
691                 xs= (but->x1+but->x2- height)/2.0;
692                 ys= (but->y1+but->y2- height)/2.0;
693         }
694
695         glEnable(GL_BLEND);
696
697         /* calculate blend color */
698         if ELEM3(but->type, TOG, ROW, TOGN) {
699                 if(but->flag & UI_SELECT);
700                 else if(but->flag & UI_ACTIVE);
701                 else blend= -60;
702         }
703         UI_icon_draw_aspect_blended(xs, ys, icon, aspect, blend);
704         
705         glDisable(GL_BLEND);
706 }
707
708
709 /* ************** DEFAULT THEME, SHADED BUTTONS ************* */
710
711
712 #define M_WHITE         UI_ThemeColorShade(colorid, 80)
713
714 #define M_ACT_LIGHT     UI_ThemeColorShade(colorid, 55)
715 #define M_LIGHT         UI_ThemeColorShade(colorid, 45)
716 #define M_HILITE        UI_ThemeColorShade(colorid, 25)
717 #define M_LMEDIUM       UI_ThemeColorShade(colorid, 10)
718 #define M_MEDIUM        UI_ThemeColor(colorid)
719 #define M_LGREY         UI_ThemeColorShade(colorid, -20)
720 #define M_GREY          UI_ThemeColorShade(colorid, -45)
721 #define M_DARK          UI_ThemeColorShade(colorid, -80)
722
723 #define M_NUMTEXT                               UI_ThemeColorShade(colorid, 25)
724 #define M_NUMTEXT_ACT_LIGHT             UI_ThemeColorShade(colorid, 35)
725
726 #define MM_WHITE        UI_ThemeColorShade(TH_BUT_NEUTRAL, 120)
727
728 /* Used for the subtle sunken effect around buttons.
729  * One option is to hardcode to white, with alpha, however it causes a 
730  * weird 'building up' efect, so it's commented out for now.
731  */
732
733 #define MM_WHITE_OP     UI_ThemeColorShadeAlpha(TH_BACK, 55, -100)
734 #define MM_WHITE_TR     UI_ThemeColorShadeAlpha(TH_BACK, 55, -255)
735
736 #define MM_LIGHT        UI_ThemeColorShade(TH_BUT_OUTLINE, 45)
737 #define MM_MEDIUM       UI_ThemeColor(TH_BUT_OUTLINE)
738 #define MM_GREY         UI_ThemeColorShade(TH_BUT_OUTLINE, -45)
739 #define MM_DARK         UI_ThemeColorShade(TH_BUT_OUTLINE, -80)
740
741 /* base shaded button */
742 static void shaded_button(float x1, float y1, float x2, float y2, float asp, int colorid, int flag, int mid)
743 {
744         /* 'mid' arg determines whether the button is in the middle of
745          * an alignment group or not. 0 = not middle, 1 = is in the middle.
746          * Done to allow cleaner drawing
747          */
748          
749         /* *** SHADED BUTTON BASE *** */
750         glShadeModel(GL_SMOOTH);
751         glBegin(GL_QUADS);
752         
753         if(flag & UI_SELECT) {
754                 if(flag & UI_ACTIVE) M_MEDIUM;
755                 else M_LGREY;
756         } else {
757                 if(flag & UI_ACTIVE) M_LIGHT;
758                 else M_HILITE;
759         }
760
761         glVertex2f(x1,y1);
762         glVertex2f(x2,y1);
763
764         if(flag & UI_SELECT) {
765                 if(flag & UI_ACTIVE) M_LGREY;
766                 else M_GREY;
767         } else {
768                 if(flag & UI_ACTIVE) M_ACT_LIGHT;
769                 else M_LIGHT;
770         }
771
772         glVertex2f(x2,(y2-(y2-y1)/3));
773         glVertex2f(x1,(y2-(y2-y1)/3));
774         glEnd();
775         
776
777         glShadeModel(GL_FLAT);
778         glBegin(GL_QUADS);
779         
780         if(flag & UI_SELECT) {
781                 if(flag & UI_ACTIVE) M_LGREY;
782                 else M_GREY;
783         } else {
784                 if(flag & UI_ACTIVE) M_ACT_LIGHT;
785                 else M_LIGHT;
786         }
787         
788         glVertex2f(x1,(y2-(y2-y1)/3));
789         glVertex2f(x2,(y2-(y2-y1)/3));
790         glVertex2f(x2,y2);
791         glVertex2f(x1,y2);
792
793         glEnd();
794         /* *** END SHADED BUTTON BASE *** */
795         
796         /* *** INNER OUTLINE *** */
797         /* left */
798         if(!(flag & UI_SELECT)) {
799                 glShadeModel(GL_SMOOTH);
800                 glBegin(GL_LINES);
801                 M_MEDIUM;
802                 glVertex2f(x1+1,y1+2);
803                 M_WHITE;
804                 glVertex2f(x1+1,y2);
805                 glEnd();
806         }
807         
808         /* right */
809                 if(!(flag & UI_SELECT)) {
810                 glShadeModel(GL_SMOOTH);
811                 glBegin(GL_LINES);
812                 M_MEDIUM;
813                 glVertex2f(x2-1,y1+2);
814                 M_WHITE;
815                 glVertex2f(x2-1,y2);
816                 glEnd();
817         }
818         
819         glShadeModel(GL_FLAT);
820         
821         /* top */
822         if(flag & UI_SELECT) {
823                 if(flag & UI_ACTIVE) M_LGREY;
824                 else M_GREY;
825         } else {
826                 if(flag & UI_ACTIVE) M_WHITE;
827                 else M_WHITE;
828         }
829
830         fdrawline(x1, (y2-1), x2, (y2-1));
831         
832         /* bottom */
833         if(flag & UI_SELECT) {
834                 if(flag & UI_ACTIVE) M_MEDIUM;
835                 else M_LGREY;
836         } else {
837                 if(flag & UI_ACTIVE) M_LMEDIUM;
838                 else M_MEDIUM;
839         }
840         fdrawline(x1, (y1+1), x2, (y1+1));
841         /* *** END INNER OUTLINE *** */
842         
843         /* *** OUTER OUTLINE *** */
844         if (mid) {
845                 // we draw full outline, its not AA, and it works better button mouse-over hilite
846                 MM_DARK;
847                 
848                 // left right
849                 fdrawline(x1, y1, x1, y2);
850                 fdrawline(x2, y1, x2, y2);
851         
852                 // top down
853                 fdrawline(x1, y2, x2, y2);
854                 fdrawline(x1, y1, x2, y1); 
855         } else {
856                 MM_DARK;
857                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 1.5);
858         }
859         /* END OUTER OUTLINE */
860 }
861
862 /* base flat button */
863 static void flat_button(float x1, float y1, float x2, float y2, float asp, int colorid, int flag, int mid)
864 {
865         /* 'mid' arg determines whether the button is in the middle of
866          * an alignment group or not. 0 = not middle, 1 = is in the middle.
867          * Done to allow cleaner drawing
868          */
869          
870         /* *** FLAT TEXT/NUM FIELD *** */
871         glShadeModel(GL_FLAT);
872         if(flag & UI_SELECT) {
873                 if(flag & UI_ACTIVE) M_LGREY;
874                 else M_GREY;
875         }
876         else {
877                 if(flag & UI_ACTIVE) M_NUMTEXT_ACT_LIGHT;
878                 else M_NUMTEXT;
879         }
880
881         glRectf(x1, y1, x2, y2);
882         /* *** END FLAT TEXT/NUM FIELD *** */
883         
884         /* *** OUTER OUTLINE *** */
885         if (mid) {
886                 // we draw full outline, its not AA, and it works better button mouse-over hilite
887                 MM_DARK;
888                 
889                 // left right
890                 fdrawline(x1, y1, x1, y2);
891                 fdrawline(x2, y1, x2, y2);
892         
893                 // top down
894                 fdrawline(x1, y2, x2, y2);
895                 fdrawline(x1, y1, x2, y1); 
896         } else {
897                 MM_DARK;
898                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 1.5);
899         }
900         /* END OUTER OUTLINE */
901 }
902
903 /* shaded round button */
904 static void round_button_shaded(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag, int rad)
905 {
906         float shadefac;
907         
908         /* colour shading */
909         if (flag & UI_SELECT) {
910                 shadefac = -0.05;
911                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, -40);
912                 else UI_ThemeColorShade(colorid, -30);  
913         } else {
914                 shadefac = 0.05;
915                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, +30);
916                 else UI_ThemeColorShade(colorid, +20);                  
917         }
918         /* end colour shading */
919         
920         
921         /* the shaded base */
922         gl_round_box_shade(GL_POLYGON, x1, y1, x2, y2, rad, shadefac, -shadefac);
923         
924         /* outline */
925         UI_ThemeColorBlendShade(TH_BUT_OUTLINE, TH_BACK, 0.1, -40);
926         
927         uiRoundRectFakeAA(x1, y1, x2, y2, rad, asp);
928         /* end outline */       
929 }
930
931 /* base round flat button */
932 static void round_button_flat(int colorid, float asp, float x1, float y1, float x2, float y2, int flag, float rad)
933 {       
934         /* colour shading */
935         if(flag & UI_SELECT) {
936                 if (flag & UI_ACTIVE) UI_ThemeColorShade(colorid, -20);
937                 else UI_ThemeColorShade(colorid, -45);  
938         }
939         else {
940                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 35);
941                 else UI_ThemeColorShade(colorid, 25);
942         }
943         /* end colour shading */
944         
945         /* the solid base */
946         gl_round_box(GL_POLYGON, x1, y1, x2, y2, rad);
947         
948         /* outline */
949         UI_ThemeColorBlendShade(TH_BUT_OUTLINE, TH_BACK, 0.1, -30);
950         
951         uiRoundRectFakeAA(x1, y1, x2, y2, rad, asp);
952         /* end outline */
953 }
954
955 static void ui_checkmark_box(int colorid, float x1, float y1, float x2, float y2)
956 {
957         uiSetRoundBox(15);
958         UI_ThemeColorShade(colorid, -5);
959         gl_round_box_shade(GL_POLYGON, x1+4, (y1+(y2-y1)/2)-5, x1+14, (y1+(y2-y1)/2)+4, 2, -0.04, 0.03);
960         
961         UI_ThemeColorShade(colorid, -30);
962         gl_round_box(GL_LINE_LOOP, x1+4, (y1+(y2-y1)/2)-5, x1+14, (y1+(y2-y1)/2)+4, 2);
963
964 }
965 static void ui_checkmark(float x1, float y1, float x2, float y2)
966 {
967         glEnable( GL_LINE_SMOOTH );
968         glEnable( GL_BLEND );
969         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
970         glLineWidth(1.5);
971         
972         glBegin( GL_LINE_STRIP );
973         glVertex2f(x1+5, (y1+(y2-y1)/2)-1);
974         glVertex2f(x1+8, (y1+(y2-y1)/2)-4);
975         glVertex2f(x1+13, (y1+(y2-y1)/2)+5);
976         glEnd();
977         
978         glLineWidth(1.0);
979         glDisable( GL_BLEND );
980         glDisable( GL_LINE_SMOOTH );    
981 }
982
983 /* small side double arrow for iconrow */
984 static void ui_iconrow_arrows(float x1, float y1, float x2, float y2)
985 {
986         glEnable( GL_POLYGON_SMOOTH );
987         glEnable( GL_BLEND );
988         
989         glShadeModel(GL_FLAT);
990         glBegin(GL_TRIANGLES);
991         glVertex2f((short)x2-2,(short)(y2-(y2-y1)/2)+1);
992         glVertex2f((short)x2-6,(short)(y2-(y2-y1)/2)+1);
993         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2)+4);
994         glEnd();
995                 
996         glBegin(GL_TRIANGLES);
997         glVertex2f((short)x2-2,(short)(y2-(y2-y1)/2) -1);
998         glVertex2f((short)x2-6,(short)(y2-(y2-y1)/2) -1);
999         glVertex2f((short)x2-4,(short)(y2-(y2-y1)/2) -4);
1000         glEnd();
1001         
1002         glDisable( GL_BLEND );
1003         glDisable( GL_POLYGON_SMOOTH );
1004 }
1005
1006 /* side double arrow for menu */
1007 static void ui_menu_arrows(float x1, float y1, float x2, float y2)
1008 {
1009         /* 'point' first, then two base vertices */
1010         uiTriangleFakeAA(x2-9, (y2-(y2-y1)/2)+6,
1011                                         x2-6, (y2-(y2-y1)/2)+2,
1012                                         x2-11, (y2-(y2-y1)/2)+2);
1013         
1014         uiTriangleFakeAA(x2-8, (y2-(y2-y1)/2)-6,
1015                                         x2-6, (y2-(y2-y1)/2)-2,
1016                                         x2-11, (y2-(y2-y1)/2)-2);
1017 }
1018
1019 /* left/right arrows for number fields */
1020 static void ui_num_arrows(float x1, float y1, float x2, float y2)
1021 {
1022         if( x2-x1 > 25) {       // 25 is a bit arbitrary, but small buttons cant have arrows
1023
1024                 /* 'point' first, then two base vertices */
1025                 uiTriangleFakeAA(x1+4, y2-(y2-y1)/2,
1026                                                 x1+9, y2-(y2-y1)/2+3,
1027                                                 x1+9, y2-(y2-y1)/2-3);
1028
1029                 uiTriangleFakeAA(x2-4, y2-(y2-y1)/2,
1030                                                 x2-9, y2-(y2-y1)/2+3,
1031                                                 x2-9, y2-(y2-y1)/2-3);
1032         }
1033 }
1034
1035
1036 /* changing black/white for TOG3 buts */
1037 static void ui_tog3_invert(float x1, float y1, float x2, float y2, int seltype)
1038 {
1039
1040         if (seltype == 0) {
1041                 UI_ThemeColorShade(TH_BUT_SETTING, -120); 
1042                 
1043                 glEnable( GL_LINE_SMOOTH );
1044                 glEnable( GL_BLEND );
1045                 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1046                 glLineWidth(1.0);
1047                 
1048                 fdrawline(x1+10, (y1+(y2-y1)/2+4), x1+10, (y1+(y2-y1)/2)-4);
1049                 fdrawline(x1+6, (y1+(y2-y1)/2), x1+14, (y1+(y2-y1)/2));
1050                 
1051                 glLineWidth(1.0);
1052                 glDisable( GL_BLEND );
1053                 glDisable( GL_LINE_SMOOTH );
1054         } else {
1055                 /* horiz line */
1056                 UI_ThemeColorShade(TH_BUT_SETTING, -120);
1057                 
1058                 glEnable( GL_LINE_SMOOTH );
1059                 glEnable( GL_BLEND );
1060                 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1061                 glLineWidth(1.0);
1062                 
1063                 fdrawline(x1+6, (y1+(y2-y1)/2), x1+14, (y1+(y2-y1)/2));
1064                 
1065                 glLineWidth(1.0);
1066                 glDisable( GL_BLEND );
1067                 glDisable( GL_LINE_SMOOTH );
1068                 
1069         }
1070 }
1071
1072 /* roundshaded button/popup menu/iconrow drawing code */
1073 static void ui_roundshaded_button(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1074 {
1075         float rad, maxrad;
1076         int align= (flag & UI_BUT_ALIGN);
1077         
1078         /* rounded corners */
1079         if (ELEM4(type, MENU, ROW, ICONROW, ICONTEXTROW)) maxrad = 5.0;
1080         else maxrad= 10.0;
1081         
1082         rad= (y2-y1)/2.0;
1083         if (rad>(x2-x1)/2) rad = (x2-x1)/2;
1084         if (rad > maxrad) rad = maxrad;
1085
1086         /* end rounded corners */
1087         
1088         /* alignment */
1089         if(align) {
1090                 switch(align) {
1091                         case UI_BUT_ALIGN_TOP:
1092                                 uiSetRoundBox(12);
1093                                 break;
1094                         case UI_BUT_ALIGN_DOWN:
1095                                 uiSetRoundBox(3);
1096                                 break;
1097                         case UI_BUT_ALIGN_LEFT:
1098                                 uiSetRoundBox(6);
1099                                 break;
1100                         case UI_BUT_ALIGN_RIGHT:
1101                                 uiSetRoundBox(9);
1102                                 break;
1103                                 
1104                         case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
1105                                 uiSetRoundBox(1);
1106                                 break;
1107                         case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
1108                                 uiSetRoundBox(2);
1109                                 break;
1110                         case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
1111                                 uiSetRoundBox(8);
1112                                 break;
1113                         case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
1114                                 uiSetRoundBox(4);
1115                                 break;
1116                                 
1117                         default:
1118                                 uiSetRoundBox(0);
1119                                 break;
1120                 }
1121         } 
1122         else {
1123                 uiSetRoundBox(15);
1124         }
1125         /* end alignment */
1126         
1127         
1128         /* draw the base button */
1129         round_button_shaded(type, colorid, asp, x1, y1, x2, y2, flag, rad);
1130         
1131         /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
1132         switch(type) {
1133                 case ICONROW:
1134                 case ICONTEXTROW:                       
1135                         /* iconrow double arrow  */
1136                         if(flag & UI_SELECT) {
1137                                 UI_ThemeColorShade(colorid, -80);
1138                         } else {
1139                                 UI_ThemeColorShade(colorid, -45);
1140                         }
1141                                 ui_iconrow_arrows(x1, y1, x2, y2);
1142                         /* end iconrow double arrow */
1143                         break;
1144                 case MENU:
1145                         /* menu double arrow  */
1146                         if(flag & UI_SELECT) {
1147                                 UI_ThemeColorShade(colorid, -110);
1148                         } else {
1149                                 UI_ThemeColorShade(colorid, -80);
1150                         }
1151                         ui_menu_arrows(x1, y1, x2, y2);
1152                         /* end menu double arrow */
1153                         break;
1154         }       
1155 }
1156
1157 static void ui_roundshaded_flat(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1158 {
1159         float rad, maxrad=10.0;
1160         int align= (flag & UI_BUT_ALIGN);
1161         
1162         /* rounded corners */
1163         rad= (y2-y1)/2.0;
1164         if (rad>(x2-x1)/2) rad = (x2-x1)/2;
1165         if (maxrad) {
1166                 if (rad > maxrad) rad = maxrad;
1167         }
1168         /* end rounded corners */
1169         
1170         /* alignment */
1171         if(align) {
1172                 switch(align) {
1173                         case UI_BUT_ALIGN_TOP:
1174                                 uiSetRoundBox(12);
1175                                 break;
1176                         case UI_BUT_ALIGN_DOWN:
1177                                 uiSetRoundBox(3);
1178                                 break;
1179                         case UI_BUT_ALIGN_LEFT:
1180                                 uiSetRoundBox(6);
1181                                 break;
1182                         case UI_BUT_ALIGN_RIGHT:
1183                                 uiSetRoundBox(9);
1184                                 break;
1185                                 
1186                         case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
1187                                 uiSetRoundBox(1);
1188                                 break;
1189                         case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
1190                                 uiSetRoundBox(2);
1191                                 break;
1192                         case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
1193                                 uiSetRoundBox(8);
1194                                 break;
1195                         case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
1196                                 uiSetRoundBox(4);
1197                                 break;
1198                                 
1199                         default:
1200                                 uiSetRoundBox(0);
1201                                 break;
1202                 }
1203         } 
1204         else {
1205                 uiSetRoundBox(15);
1206         }
1207         /* end alignment */
1208         
1209         /* draw the base button */
1210         round_button_flat(colorid, asp, x1, y1, x2, y2, flag, rad);
1211         
1212         /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
1213         switch(type) {
1214                 case TOG:
1215                 case TOGN:
1216                 case TOG3:
1217                         if (!(flag & UI_HAS_ICON)) {
1218                                 /* check to see that there's room for the check mark
1219                                 * draw a check mark, or if it's a TOG3, draw a + or - */
1220                                 if (x2 - x1 > 20) {
1221                                         ui_checkmark_box(colorid, x1, y1, x2, y2);
1222                                         
1223                                         /* TOG3 is handled with ui_tog3_invert() 
1224                                                 *  remember to update checkmark drawing there too*/
1225                                         if((flag & UI_SELECT) && (type != TOG3)) {
1226                                                 UI_ThemeColorShade(colorid, -140);
1227         
1228                                                 ui_checkmark(x1, y1, x2, y2);
1229                                         }
1230                                         /* draw a dot: alternate, for layers etc. */
1231                                 } else if(flag & UI_SELECT) {
1232                                         uiSetRoundBox(15);
1233                                         UI_ThemeColorShade(colorid, -60);
1234                                         
1235                                         glPushMatrix();
1236                                         glTranslatef((x1+(x2-x1)/2), (y1+(y2-y1)/2), 0.0);
1237                                         
1238                                         /* circle */
1239                                         glutil_draw_filled_arc(0.0, M_PI*2.0, 2, 16);
1240                                         
1241                                         glEnable( GL_LINE_SMOOTH );
1242                                         glEnable( GL_BLEND );
1243                                         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1244                                         
1245                                         /* smooth outline */
1246                                         glutil_draw_lined_arc(0.0, M_PI*2.0, 2, 16);
1247                                         
1248                                         glDisable( GL_BLEND );
1249                                         glDisable( GL_LINE_SMOOTH );
1250                                         
1251                                         glPopMatrix();
1252                                 }
1253                         }
1254                         break;
1255                 case NUM:
1256                         /* side arrows */
1257                         if(flag & UI_SELECT) {
1258                                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, -70);
1259                                 else UI_ThemeColorShade(colorid, -70);
1260                         } else {
1261                                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, -40);
1262                                 else UI_ThemeColorShade(colorid, -20);
1263                         }
1264                         
1265                         ui_num_arrows(x1, y1, x2, y2);
1266                         /* end side arrows */
1267                         break;
1268         }       
1269 }
1270
1271 /* roundshaded theme callback */
1272 static void ui_draw_roundshaded(int type, int colorid, float aspect, float x1, float y1, float x2, float y2, int flag)
1273 {
1274         
1275         switch(type) {
1276                 case TOG:
1277                 case TOGN:
1278                 case TOG3:
1279                 case SLI:
1280                 case NUMSLI:
1281                 case HSVSLI:
1282                 case TEX:
1283                 case IDPOIN:
1284                 case NUM:
1285                         ui_roundshaded_flat(type, colorid, aspect, x1, y1, x2, y2, flag);
1286                         break;
1287                 case ICONROW: 
1288                 case ICONTEXTROW: 
1289                 case MENU: 
1290                 default: 
1291                         ui_roundshaded_button(type, colorid, aspect, x1, y1, x2, y2, flag);
1292         }
1293         
1294 }
1295
1296 /* button/popup menu/iconrow drawing code */
1297 static void ui_default_button(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1298 {
1299         int align= (flag & UI_BUT_ALIGN);
1300
1301         if(align) {
1302         
1303                 /* *** BOTTOM OUTER SUNKEN EFFECT *** */
1304                 if (!((align == UI_BUT_ALIGN_DOWN) ||
1305                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT)) ||
1306                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT)))) {
1307                         glEnable(GL_BLEND);
1308                         MM_WHITE_OP;
1309                         fdrawline(x1, y1-1, x2, y1-1);  
1310                         glDisable(GL_BLEND);
1311                 }
1312                 /* *** END BOTTOM OUTER SUNKEN EFFECT *** */
1313                 
1314                 switch(align) {
1315                 case UI_BUT_ALIGN_TOP:
1316                         uiSetRoundBox(12);
1317                         
1318                         /* last arg in shaded_button() determines whether the button is in the middle of
1319                          * an alignment group or not. 0 = not middle, 1 = is in the middle.
1320                          * Done to allow cleaner drawing
1321                          */
1322                          
1323                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1324                         break;
1325                 case UI_BUT_ALIGN_DOWN:
1326                         uiSetRoundBox(3);
1327                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1328                         break;
1329                 case UI_BUT_ALIGN_LEFT:
1330                         
1331                         /* RIGHT OUTER SUNKEN EFFECT */
1332                         glEnable(GL_BLEND);
1333                         glShadeModel(GL_SMOOTH);
1334                         glBegin(GL_LINES);
1335                         MM_WHITE_OP;
1336                         glVertex2f(x2+1,y1);
1337                         MM_WHITE_TR;
1338                         glVertex2f(x2+1,y2);
1339                         glEnd();
1340                         glDisable(GL_BLEND);
1341                         
1342                         uiSetRoundBox(6);
1343                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1344                         break;
1345                 case UI_BUT_ALIGN_RIGHT:
1346                 
1347                         /* LEFT OUTER SUNKEN EFFECT */
1348                         glEnable(GL_BLEND);
1349                         glShadeModel(GL_SMOOTH);
1350                         glBegin(GL_LINES);
1351                         MM_WHITE_OP;
1352                         glVertex2f(x1-1,y1);
1353                         MM_WHITE_TR;
1354                         glVertex2f(x1-1,y2);
1355                         glEnd();
1356                         glDisable(GL_BLEND);
1357                 
1358                         uiSetRoundBox(9);
1359                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1360                         break;
1361                         
1362                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
1363                         uiSetRoundBox(1);
1364                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1365                         break;
1366                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
1367                         uiSetRoundBox(2);
1368                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1369                         break;
1370                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
1371                 
1372                         /* LEFT OUTER SUNKEN EFFECT */
1373                         glEnable(GL_BLEND);
1374                         glShadeModel(GL_SMOOTH);
1375                         glBegin(GL_LINES);
1376                         MM_WHITE_OP;
1377                         glVertex2f(x1-1,y1);
1378                         MM_WHITE_TR;
1379                         glVertex2f(x1-1,y2);
1380                         glEnd();
1381                         glDisable(GL_BLEND);
1382                 
1383                         uiSetRoundBox(8);
1384                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1385                         break;
1386                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
1387                 
1388                         /* RIGHT OUTER SUNKEN EFFECT */
1389                         glEnable(GL_BLEND);
1390                         glShadeModel(GL_SMOOTH);
1391                         glBegin(GL_LINES);
1392                         MM_WHITE_OP;
1393                         glVertex2f(x2+1,y1);
1394                         MM_WHITE_TR;
1395                         glVertex2f(x2+1,y2);
1396                         glEnd();
1397                         glDisable(GL_BLEND);
1398                         
1399                         uiSetRoundBox(4);
1400                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1401                         break;
1402                         
1403                 default:
1404                         shaded_button(x1, y1, x2, y2, asp, colorid, flag, 1);
1405                         break;
1406                 }
1407         } 
1408         else {  
1409                 glEnable(GL_BLEND);
1410                 glShadeModel(GL_SMOOTH);
1411                 
1412                 /* BOTTOM OUTER SUNKEN EFFECT */
1413                 MM_WHITE_OP;
1414                 fdrawline(x1, y1-1, x2, y1-1);  
1415                 
1416                 /* LEFT OUTER SUNKEN EFFECT */
1417                 glBegin(GL_LINES);
1418                 MM_WHITE_OP;
1419                 glVertex2f(x1-1,y1);
1420                 MM_WHITE_TR;
1421                 glVertex2f(x1-1,y2);
1422                 glEnd();
1423                 
1424                 /* RIGHT OUTER SUNKEN EFFECT */
1425                 glBegin(GL_LINES);
1426                 MM_WHITE_OP;
1427                 glVertex2f(x2+1,y1);
1428                 MM_WHITE_TR;
1429                 glVertex2f(x2+1,y2);
1430                 glEnd();
1431                 
1432                 glDisable(GL_BLEND);
1433         
1434                 uiSetRoundBox(15);
1435                 shaded_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1436         }
1437         
1438         /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
1439         switch(type) {
1440         case ICONROW:
1441         case ICONTEXTROW:
1442                 /* DARKENED AREA */
1443                 glEnable(GL_BLEND);
1444                 
1445                 glColor4ub(0, 0, 0, 30);
1446                 glRectf(x2-9, y1, x2, y2);
1447         
1448                 glDisable(GL_BLEND);
1449                 /* END DARKENED AREA */
1450         
1451                 /* ICONROW DOUBLE-ARROW  */
1452                 M_DARK;
1453                 ui_iconrow_arrows(x1, y1, x2, y2);
1454                 /* END ICONROW DOUBLE-ARROW */
1455                 break;
1456         case MENU:
1457                 /* DARKENED AREA */
1458                 glEnable(GL_BLEND);
1459                 
1460                 glColor4ub(0, 0, 0, 30);
1461                 glRectf(x2-18, y1, x2, y2);
1462         
1463                 glDisable(GL_BLEND);
1464                 /* END DARKENED AREA */
1465         
1466                 /* MENU DOUBLE-ARROW  */
1467                 M_DARK;
1468                 ui_menu_arrows(x1, y1, x2, y2);
1469                 /* MENU DOUBLE-ARROW */
1470                 break;
1471         }       
1472 }
1473
1474 /* number/text field drawing code */
1475 static void ui_default_flat(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1476 {
1477         int align= (flag & UI_BUT_ALIGN);
1478
1479         if(align) {
1480         
1481                 /* *** BOTTOM OUTER SUNKEN EFFECT *** */
1482                 if (!((align == UI_BUT_ALIGN_DOWN) ||
1483                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT)) ||
1484                         (align == (UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT)))) {
1485                         glEnable(GL_BLEND);
1486                         MM_WHITE_OP;
1487                         fdrawline(x1, y1-1, x2, y1-1);  
1488                         glDisable(GL_BLEND);
1489                 }
1490                 /* *** END BOTTOM OUTER SUNKEN EFFECT *** */
1491                 
1492                 switch(align) {
1493                 case UI_BUT_ALIGN_TOP:
1494                         uiSetRoundBox(12);
1495                         
1496                         /* last arg in shaded_button() determines whether the button is in the middle of
1497                          * an alignment group or not. 0 = not middle, 1 = is in the middle.
1498                          * Done to allow cleaner drawing
1499                          */
1500                          
1501                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1502                         break;
1503                 case UI_BUT_ALIGN_DOWN:
1504                         uiSetRoundBox(3);
1505                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1506                         break;
1507                 case UI_BUT_ALIGN_LEFT:
1508                         
1509                         /* RIGHT OUTER SUNKEN EFFECT */
1510                         glEnable(GL_BLEND);
1511                         glShadeModel(GL_SMOOTH);
1512                         glBegin(GL_LINES);
1513                         MM_WHITE_OP;
1514                         glVertex2f(x2+1,y1);
1515                         MM_WHITE_TR;
1516                         glVertex2f(x2+1,y2);
1517                         glEnd();
1518                         glDisable(GL_BLEND);
1519                         
1520                         uiSetRoundBox(6);
1521                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1522                         break;
1523                 case UI_BUT_ALIGN_RIGHT:
1524                 
1525                         /* LEFT OUTER SUNKEN EFFECT */
1526                         glEnable(GL_BLEND);
1527                         glShadeModel(GL_SMOOTH);
1528                         glBegin(GL_LINES);
1529                         MM_WHITE_OP;
1530                         glVertex2f(x1-1,y1);
1531                         MM_WHITE_TR;
1532                         glVertex2f(x1-1,y2);
1533                         glEnd();
1534                         glDisable(GL_BLEND);
1535                 
1536                         uiSetRoundBox(9);
1537                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1538                         break;
1539                         
1540                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
1541                         uiSetRoundBox(1);
1542                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1543                         break;
1544                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
1545                         uiSetRoundBox(2);
1546                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1547                         break;
1548                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
1549                 
1550                         /* LEFT OUTER SUNKEN EFFECT */
1551                         glEnable(GL_BLEND);
1552                         glShadeModel(GL_SMOOTH);
1553                         glBegin(GL_LINES);
1554                         MM_WHITE_OP;
1555                         glVertex2f(x1-1,y1);
1556                         MM_WHITE_TR;
1557                         glVertex2f(x1-1,y2);
1558                         glEnd();
1559                         glDisable(GL_BLEND);
1560                 
1561                         uiSetRoundBox(8);
1562                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1563                         break;
1564                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
1565                 
1566                         /* RIGHT OUTER SUNKEN EFFECT */
1567                         glEnable(GL_BLEND);
1568                         glShadeModel(GL_SMOOTH);
1569                         glBegin(GL_LINES);
1570                         MM_WHITE_OP;
1571                         glVertex2f(x2+1,y1);
1572                         MM_WHITE_TR;
1573                         glVertex2f(x2+1,y2);
1574                         glEnd();
1575                         glDisable(GL_BLEND);
1576                         
1577                         uiSetRoundBox(4);
1578                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1579                         break;
1580                         
1581                 default:
1582                         flat_button(x1, y1, x2, y2, asp, colorid, flag, 1);
1583                         break;
1584                 }
1585         } 
1586         else {
1587         
1588                 glEnable(GL_BLEND);
1589                 glShadeModel(GL_SMOOTH);
1590                 
1591                 /* BOTTOM OUTER SUNKEN EFFECT */
1592                 MM_WHITE_OP;
1593                 fdrawline(x1, y1-1, x2, y1-1);  
1594                 
1595                 /* LEFT OUTER SUNKEN EFFECT */
1596                 glBegin(GL_LINES);
1597                 MM_WHITE_OP;
1598                 glVertex2f(x1-1,y1);
1599                 MM_WHITE_TR;
1600                 glVertex2f(x1-1,y2);
1601                 glEnd();
1602                 
1603                 /* RIGHT OUTER SUNKEN EFFECT */
1604                 glBegin(GL_LINES);
1605                 MM_WHITE_OP;
1606                 glVertex2f(x2+1,y1);
1607                 MM_WHITE_TR;
1608                 glVertex2f(x2+1,y2);
1609                 glEnd();
1610                 
1611                 glDisable(GL_BLEND);
1612
1613                 uiSetRoundBox(15);
1614                 flat_button(x1, y1, x2, y2, asp, colorid, flag, 0);
1615         }
1616         
1617         /* *** EXTRA DRAWING FOR SPECIFIC CONTROL TYPES *** */
1618         switch(type) {
1619         case NUM:
1620         case NUMABS:
1621                 /* SIDE ARROWS */
1622                 /* left */
1623                 if(flag & UI_SELECT) {
1624                         if(flag & UI_ACTIVE) M_DARK;
1625                         else M_DARK;
1626                 } else {
1627                         if(flag & UI_ACTIVE) M_GREY;
1628                         else M_LGREY;
1629                 }
1630                 
1631                 ui_num_arrows(x1, y1, x2, y2);
1632                 /* END SIDE ARROWS */
1633         }
1634 }
1635
1636 #if 0
1637 static void ui_default_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag)
1638 {
1639         float ymid, yc;
1640
1641         /* the slider background line */
1642         ymid= (y1+y2)/2.0;
1643         //yc= 2.5*aspect;       // height of center line
1644         yc = 2.3; // height of center line
1645         
1646         if(flag & UI_SELECT) 
1647                         UI_ThemeColorShade(TH_BUT_NUM, -5);
1648         else {
1649                 if(flag & UI_ACTIVE) 
1650                         UI_ThemeColorShade(TH_BUT_NUM, +35); 
1651                 else
1652                         UI_ThemeColorShade(TH_BUT_NUM, +25); 
1653         }
1654
1655         glRectf(x1, ymid-yc, x2, ymid+yc);
1656         
1657         /* top inner bevel */
1658         if(flag & UI_SELECT) UI_ThemeColorShade(TH_BUT_NUM, -40); 
1659         else UI_ThemeColorShade(TH_BUT_NUM, -5); 
1660         fdrawline(x1+1, ymid+yc, x2, ymid+yc);
1661         
1662         /* bottom inner bevel */
1663         if(flag & UI_SELECT) UI_ThemeColorShade(TH_BUT_NUM, +15); 
1664         else UI_ThemeColorShade(TH_BUT_NUM, +45); 
1665         fdrawline(x1+1, ymid-yc, x2, ymid-yc);
1666         
1667         
1668         /* the movable slider */
1669         if(flag & UI_SELECT) UI_ThemeColorShade(TH_BUT_NUM, +80); 
1670         else UI_ThemeColorShade(TH_BUT_NUM, -45); 
1671
1672         glShadeModel(GL_SMOOTH);
1673         glBegin(GL_QUADS);
1674
1675         UI_ThemeColorShade(TH_BUT_NUM, -45); 
1676
1677         glVertex2f(x1,     y1+2.5);
1678         glVertex2f(x1+fac, y1+2.5);
1679
1680         UI_ThemeColor(TH_BUT_NUM); 
1681
1682         glVertex2f(x1+fac, y2-2.5);
1683         glVertex2f(x1,     y2-2.5);
1684
1685         glEnd();
1686         
1687
1688         /* slider handle center */
1689         glShadeModel(GL_SMOOTH);
1690         glBegin(GL_QUADS);
1691
1692         UI_ThemeColor(TH_BUT_NUM); 
1693         glVertex2f(x1+fac-3, y1+2);
1694         glVertex2f(x1+fac, y1+4);
1695         UI_ThemeColorShade(TH_BUT_NUM, +80); 
1696         glVertex2f(x1+fac, y2-2);
1697         glVertex2f(x1+fac-3, y2-2);
1698
1699         glEnd();
1700         
1701         /* slider handle left bevel */
1702         UI_ThemeColorShade(TH_BUT_NUM, +70); 
1703         fdrawline(x1+fac-3, y2-2, x1+fac-3, y1+2);
1704         
1705         /* slider handle right bevel */
1706         UI_ThemeColorShade(TH_BUT_NUM, -35); 
1707         fdrawline(x1+fac, y2-2, x1+fac, y1+2);
1708
1709         glShadeModel(GL_FLAT);
1710 }
1711 #endif
1712
1713 /* default theme callback */
1714 static void ui_draw_default(int type, int colorid, float aspect, float x1, float y1, float x2, float y2, int flag)
1715 {
1716
1717         switch(type) {
1718         case TEX:
1719         case IDPOIN:
1720         case NUM:
1721         case NUMABS:
1722                 ui_default_flat(type, colorid, aspect, x1, y1, x2, y2, flag);
1723                 break;
1724         case ICONROW: 
1725         case ICONTEXTROW: 
1726         case MENU: 
1727         default: 
1728                 ui_default_button(type, colorid, aspect, x1, y1, x2, y2, flag);
1729         }
1730
1731 }
1732
1733
1734 /* *************** OLDSKOOL THEME ***************** */
1735
1736 static void ui_draw_outlineX(float x1, float y1, float x2, float y2, float asp1)
1737 {
1738         float vec[2];
1739         
1740         glBegin(GL_LINE_LOOP);
1741         vec[0]= x1+asp1; vec[1]= y1-asp1;
1742         glVertex2fv(vec);
1743         vec[0]= x2-asp1; 
1744         glVertex2fv(vec);
1745         vec[0]= x2+asp1; vec[1]= y1+asp1;
1746         glVertex2fv(vec);
1747         vec[1]= y2-asp1;
1748         glVertex2fv(vec);
1749         vec[0]= x2-asp1; vec[1]= y2+asp1;
1750         glVertex2fv(vec);
1751         vec[0]= x1+asp1;
1752         glVertex2fv(vec);
1753         vec[0]= x1-asp1; vec[1]= y2-asp1;
1754         glVertex2fv(vec);
1755         vec[1]= y1+asp1;
1756         glVertex2fv(vec);
1757         glEnd();                
1758         
1759 }
1760
1761
1762 static void ui_draw_oldskool(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1763 {
1764         /* paper */
1765         if(flag & UI_SELECT) {
1766                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, -40);
1767                 else UI_ThemeColorShade(colorid, -30);
1768         }
1769         else {
1770                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, +30);
1771                 else UI_ThemeColorShade(colorid, +20);
1772         }
1773         
1774         glRectf(x1+1, y1+1, x2-1, y2-1);
1775
1776         x1+= asp;
1777         x2-= asp;
1778         y1+= asp;
1779         y2-= asp;
1780
1781         /* below */
1782         if(flag & UI_SELECT) UI_ThemeColorShade(colorid, 0);
1783         else UI_ThemeColorShade(colorid, -30);
1784         fdrawline(x1, y1, x2, y1);
1785
1786         /* right */
1787         fdrawline(x2, y1, x2, y2);
1788         
1789         /* top */
1790         if(flag & UI_SELECT) UI_ThemeColorShade(colorid, -30);
1791         else UI_ThemeColorShade(colorid, 0);
1792         fdrawline(x1, y2, x2, y2);
1793
1794         /* left */
1795         fdrawline(x1, y1, x1, y2);
1796         
1797         /* outline */
1798         glColor3ub(0,0,0);
1799         ui_draw_outlineX(x1, y1, x2, y2, asp);
1800         
1801         
1802         /* special type decorations */
1803         switch(type) {
1804         case NUM:
1805         case NUMABS:
1806                 if(flag & UI_SELECT) UI_ThemeColorShade(colorid, -60);
1807                 else UI_ThemeColorShade(colorid, -30);
1808                 ui_num_arrows(x1, y1, x2, y2);
1809                 break;
1810
1811         case ICONROW: 
1812         case ICONTEXTROW: 
1813                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 0);
1814                 else UI_ThemeColorShade(colorid, -10);
1815                 glRectf(x2-9, y1+asp, x2-asp, y2-asp);
1816
1817                 UI_ThemeColorShade(colorid, -50);
1818                 ui_iconrow_arrows(x1, y1, x2, y2);
1819                 break;
1820                 
1821         case MENU: 
1822                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 0);
1823                 else UI_ThemeColorShade(colorid, -10);
1824                 glRectf(x2-17, y1+asp, x2-asp, y2-asp);
1825
1826                 UI_ThemeColorShade(colorid, -50);
1827                 ui_menu_arrows(x1, y1, x2, y2);
1828                 break;
1829         }
1830         
1831 }
1832
1833 /* *************** BASIC ROUNDED THEME ***************** */
1834
1835 static void round_button(float x1, float y1, float x2, float y2, float asp, 
1836                                                  int colorid, int round, int menudeco, int curshade)
1837 {
1838         float rad;
1839         
1840         rad= (y2-y1)/2.0;
1841         if(rad>7.0) rad= 7.0;
1842         
1843         uiSetRoundBox(round);
1844         gl_round_box(GL_POLYGON, x1, y1, x2, y2, rad);
1845
1846         if(menudeco) {
1847                 uiSetRoundBox(round & ~9);
1848                 UI_ThemeColorShade(colorid, curshade-20);
1849                 gl_round_box(GL_POLYGON, x2-menudeco, y1, x2, y2, rad);
1850         }
1851         
1852         /* outline */
1853         UI_ThemeColorBlendShade(TH_BUT_OUTLINE, TH_BACK, 0.1, -30);
1854         
1855         uiSetRoundBox(round);
1856         uiRoundRectFakeAA(x1, y1, x2, y2, rad, asp);
1857         /* end outline */
1858 }
1859
1860 /* button in midst of alignment row */
1861 static void round_button_mid(float x1, float y1, float x2, float y2, float asp, 
1862                                                          int colorid, int align, int menudeco, int curshade)
1863 {
1864         glRectf(x1, y1, x2, y2);
1865         
1866         if(menudeco) {
1867                 UI_ThemeColorShade(colorid, curshade-20);
1868                 glRectf(x2-menudeco, y1, x2, y2);
1869         }
1870         
1871         UI_ThemeColorBlendShade(colorid, TH_BACK, 0.5, -70);
1872         // we draw full outline, its not AA, and it works better button mouse-over hilite
1873         
1874         // left right
1875         fdrawline(x1, y1, x1, y2);
1876         fdrawline(x2, y1, x2, y2);
1877
1878         // top down
1879         fdrawline(x1, y2, x2, y2);
1880         fdrawline(x1, y1, x2, y1);   
1881 }
1882
1883 static void ui_draw_round(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1884 {
1885         int align= (flag & UI_BUT_ALIGN);
1886         int curshade= 0, menudeco= 0;
1887         
1888         if(type==ICONROW || type==ICONTEXTROW) menudeco= 9;
1889         else if((type==MENU || type==BLOCK) && x2-x1>24) menudeco= 16;
1890         
1891         /* paper */
1892         if(flag & UI_SELECT) {
1893                 if(flag & UI_ACTIVE) curshade= -40;
1894                 else curshade= -30;
1895         }
1896         else {
1897                 if(flag & UI_ACTIVE) curshade= 30;
1898                 else curshade= +20;
1899         }
1900         
1901         UI_ThemeColorShade(colorid, curshade);
1902
1903         if(align) {
1904                 switch(align) {
1905                 case UI_BUT_ALIGN_TOP:
1906                         round_button(x1, y1, x2, y2, asp, colorid, 12, menudeco, curshade);
1907                         break;
1908                 case UI_BUT_ALIGN_DOWN:
1909                         round_button(x1, y1, x2, y2, asp, colorid, 3, menudeco, curshade);
1910                         break;
1911                 case UI_BUT_ALIGN_LEFT:
1912                         round_button(x1, y1, x2, y2, asp, colorid, 6, menudeco, curshade);
1913                         break;
1914                 case UI_BUT_ALIGN_RIGHT:
1915                         round_button(x1, y1, x2, y2, asp, colorid, 9, menudeco, curshade);
1916                         break;
1917                         
1918                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_RIGHT:
1919                         round_button(x1, y1, x2, y2, asp, colorid, 1, menudeco, curshade);
1920                         break;
1921                 case UI_BUT_ALIGN_DOWN|UI_BUT_ALIGN_LEFT:
1922                         round_button(x1, y1, x2, y2, asp, colorid, 2, menudeco, curshade);
1923                         break;
1924                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_RIGHT:
1925                         round_button(x1, y1, x2, y2, asp, colorid, 8, menudeco, curshade);
1926                         break;
1927                 case UI_BUT_ALIGN_TOP|UI_BUT_ALIGN_LEFT:
1928                         round_button(x1, y1, x2, y2, asp, colorid, 4, menudeco, curshade);
1929                         break;
1930                         
1931                 default:
1932                         round_button_mid(x1, y1, x2, y2, asp, colorid, align, menudeco, curshade);
1933                         break;
1934                 }
1935         } 
1936         else {
1937                 round_button(x1, y1, x2, y2, asp, colorid, 15, menudeco, curshade);
1938         }
1939
1940         /* special type decorations */
1941         switch(type) {
1942         case NUM:
1943         case NUMABS:
1944                 UI_ThemeColorShade(colorid, curshade-60);
1945                 ui_num_arrows(x1, y1, x2, y2);
1946                 break;
1947
1948         case ICONROW: 
1949         case ICONTEXTROW: 
1950                 UI_ThemeColorShade(colorid, curshade-60);
1951                 ui_iconrow_arrows(x1, y1, x2, y2);
1952                 break;
1953                 
1954         case MENU: 
1955         case BLOCK: 
1956                 UI_ThemeColorShade(colorid, curshade-60);
1957                 ui_menu_arrows(x1, y1, x2, y2);
1958                 break;
1959         }
1960 }
1961
1962 /* *************** MINIMAL THEME ***************** */
1963
1964 // theme can define an embosfunc and sliderfunc, text+icon drawing is standard, no theme.
1965
1966
1967
1968 /* super minimal button as used in logic menu */
1969 static void ui_draw_minimal(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
1970 {
1971         /* too much space between buttons */
1972         
1973         if (type==TEX || type==IDPOIN) {
1974                 x1+= asp;
1975                 x2-= (asp*2);
1976                 //y1+= asp;
1977                 y2-= asp;
1978         } else {
1979                 /* Less space between buttons looks nicer */
1980                 y2-= asp;
1981                 x2-= asp;
1982         }
1983         
1984         /* paper */
1985         if(flag & UI_SELECT) {
1986                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, -40);
1987                 else UI_ThemeColorShade(colorid, -30);
1988         }
1989         else {
1990                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, +20);
1991                 else UI_ThemeColorShade(colorid, +10);
1992         }
1993         
1994         glRectf(x1, y1, x2, y2);
1995         
1996         if (type==TEX || type==IDPOIN) {
1997                 UI_ThemeColorShade(colorid, -60);
1998
1999                 /* top */
2000                 fdrawline(x1, y2, x2, y2);
2001                 /* left */
2002                 fdrawline(x1, y1, x1, y2);
2003                 
2004                 
2005                 /* text underline, some  */ 
2006                 UI_ThemeColorShade(colorid, +50);
2007                 glEnable(GL_LINE_STIPPLE);
2008                 glLineStipple(1, 0x8888);
2009                 fdrawline(x1+(asp*2), y1+(asp*3), x2-(asp*2), y1+(asp*3));
2010                 glDisable(GL_LINE_STIPPLE);
2011                 
2012                 
2013                 UI_ThemeColorShade(colorid, +60);
2014                 /* below */
2015                 fdrawline(x1, y1, x2, y1);
2016                 /* right */
2017                 fdrawline(x2, y1, x2, y2);
2018                 
2019         } else {
2020                 if(flag & UI_SELECT) {
2021                         UI_ThemeColorShade(colorid, -60);
2022
2023                         /* top */
2024                         fdrawline(x1, y2, x2, y2);
2025                         /* left */
2026                         fdrawline(x1, y1, x1, y2);
2027                         UI_ThemeColorShade(colorid, +40);
2028
2029                         /* below */
2030                         fdrawline(x1, y1, x2, y1);
2031                         /* right */
2032                         fdrawline(x2, y1, x2, y2);
2033                 }
2034                 else {
2035                         UI_ThemeColorShade(colorid, +40);
2036
2037                         /* top */
2038                         fdrawline(x1, y2, x2, y2);
2039                         /* left */
2040                         fdrawline(x1, y1, x1, y2);
2041                         
2042                         UI_ThemeColorShade(colorid, -60);
2043                         /* below */
2044                         fdrawline(x1, y1, x2, y1);
2045                         /* right */
2046                         fdrawline(x2, y1, x2, y2);
2047                 }
2048         }
2049         
2050         /* special type decorations */
2051         switch(type) {
2052         case NUM:
2053         case NUMABS:
2054                 if(flag & UI_SELECT) UI_ThemeColorShade(colorid, -60);
2055                 else UI_ThemeColorShade(colorid, -30);
2056                 ui_num_arrows(x1, y1, x2, y2);
2057                 break;
2058
2059         case ICONROW: 
2060         case ICONTEXTROW: 
2061                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 0);
2062                 else UI_ThemeColorShade(colorid, -10);
2063                 glRectf(x2-9, y1+asp, x2-asp, y2-asp);
2064
2065                 UI_ThemeColorShade(colorid, -50);
2066                 ui_iconrow_arrows(x1, y1, x2, y2);
2067                 break;
2068                 
2069         case MENU: 
2070         case BLOCK: 
2071                 if(flag & UI_ACTIVE) UI_ThemeColorShade(colorid, 0);
2072                 else UI_ThemeColorShade(colorid, -10);
2073                 glRectf(x2-17, y1+asp, x2-asp, y2-asp);
2074
2075                 UI_ThemeColorShade(colorid, -50);
2076                 ui_menu_arrows(x1, y1, x2, y2);
2077                 break;
2078         }
2079         
2080         
2081 }
2082
2083
2084 /* fac is the slider handle position between x1 and x2 */
2085 static void ui_draw_slider(int colorid, float fac, float aspect, float x1, float y1, float x2, float y2, int flag)
2086 {
2087         float ymid, yc;
2088
2089         /* the slider background line */
2090         ymid= (y1+y2)/2.0;
2091         yc= 1.7*aspect; 
2092
2093         if(flag & UI_ACTIVE) 
2094                 UI_ThemeColorShade(colorid, -50); 
2095         else 
2096                 UI_ThemeColorShade(colorid, -40); 
2097
2098         /* left part */
2099         glRectf(x1, ymid-2.0*yc, x1+fac, ymid+2.0*yc);
2100         /* right part */
2101         glRectf(x1+fac, ymid-yc, x2, ymid+yc);
2102
2103         /* the movable slider */
2104         
2105         UI_ThemeColorShade(colorid, +70); 
2106         glRectf(x1+fac-aspect, ymid-2.0*yc, x1+fac+aspect, ymid+2.0*yc);
2107
2108 }
2109
2110 /* ************** STANDARD MENU DRAWING FUNCTION ************* */
2111
2112
2113 static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
2114 {
2115         glEnable(GL_BLEND);
2116         glShadeModel(GL_SMOOTH);
2117         
2118         /* right quad */
2119         glBegin(GL_POLYGON);
2120         glColor4ub(0, 0, 0, alpha);
2121         glVertex2f(maxx, miny);
2122         glVertex2f(maxx, maxy-shadsize);
2123         glColor4ub(0, 0, 0, 0);
2124         glVertex2f(maxx+shadsize, maxy-shadsize-shadsize);
2125         glVertex2f(maxx+shadsize, miny);
2126         glEnd();
2127         
2128         /* corner shape */
2129         glBegin(GL_POLYGON);
2130         glColor4ub(0, 0, 0, alpha);
2131         glVertex2f(maxx, miny);
2132         glColor4ub(0, 0, 0, 0);
2133         glVertex2f(maxx+shadsize, miny);
2134         glVertex2f(maxx+0.7*shadsize, miny-0.7*shadsize);
2135         glVertex2f(maxx, miny-shadsize);
2136         glEnd();
2137         
2138         /* bottom quad */               
2139         glBegin(GL_POLYGON);
2140         glColor4ub(0, 0, 0, alpha);
2141         glVertex2f(minx+shadsize, miny);
2142         glVertex2f(maxx, miny);
2143         glColor4ub(0, 0, 0, 0);
2144         glVertex2f(maxx, miny-shadsize);
2145         glVertex2f(minx+shadsize+shadsize, miny-shadsize);
2146         glEnd();
2147         
2148         glDisable(GL_BLEND);
2149         glShadeModel(GL_FLAT);
2150 }
2151
2152 void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
2153 {
2154         /* accumulated outline boxes to make shade not linear, is more pleasant */
2155         ui_shadowbox(minx, miny, maxx, maxy, 6.0, (30*alpha)>>8);
2156         ui_shadowbox(minx, miny, maxx, maxy, 4.0, (70*alpha)>>8);
2157         ui_shadowbox(minx, miny, maxx, maxy, 2.0, (100*alpha)>>8);
2158         
2159 }
2160
2161 // background for pulldowns, pullups, and other drawing temporal menus....
2162 // has to be made themable still (now only color)
2163
2164 void uiDrawMenuBox(float minx, float miny, float maxx, float maxy, short flag)
2165 {
2166         char col[4];
2167         UI_GetThemeColor4ubv(TH_MENU_BACK, col);
2168         
2169         if( (flag & UI_BLOCK_NOSHADOW)==0) {
2170                 /* accumulated outline boxes to make shade not linear, is more pleasant */
2171                 ui_shadowbox(minx, miny, maxx, maxy, 6.0, (30*col[3])>>8);
2172                 ui_shadowbox(minx, miny, maxx, maxy, 4.0, (70*col[3])>>8);
2173                 ui_shadowbox(minx, miny, maxx, maxy, 2.0, (100*col[3])>>8);
2174                 
2175                 glEnable(GL_BLEND);
2176                 glColor4ubv((GLubyte *)col);
2177                 glRectf(minx-1, miny, minx, maxy);      // 1 pixel on left, to distinguish sublevel menus
2178         }
2179         glEnable(GL_BLEND);
2180         glColor4ubv((GLubyte *)col);
2181         glRectf(minx, miny, maxx, maxy);
2182         glDisable(GL_BLEND);
2183 }
2184
2185
2186
2187 /* pulldown menu item */
2188 static void ui_draw_pulldown_item(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
2189 {
2190         char col[4];
2191         
2192         UI_GetThemeColor4ubv(TH_MENU_BACK, col);
2193         if(col[3]!=255) {
2194                 glEnable(GL_BLEND);
2195         }
2196         
2197         if((flag & UI_ACTIVE) && type!=LABEL) {
2198                 UI_ThemeColor4(TH_MENU_HILITE);
2199                 glRectf(x1, y1, x2, y2);
2200         
2201
2202         } else {
2203                 UI_ThemeColor4(colorid);        // is set at TH_MENU_ITEM when pulldown opened.
2204                 glRectf(x1, y1, x2, y2);
2205         }
2206
2207         glDisable(GL_BLEND);
2208 }
2209
2210 /* pulldown menu calling button */
2211 static void ui_draw_pulldown_round(int type, int colorid, float asp, float x1, float y1, float x2, float y2, int flag)
2212 {
2213         
2214         if(flag & UI_ACTIVE) {
2215                 UI_ThemeColor(TH_MENU_HILITE);
2216
2217                 uiSetRoundBox(15);
2218                 gl_round_box(GL_POLYGON, x1, y1+3, x2, y2-3, 7.0);
2219
2220                 glEnable( GL_LINE_SMOOTH );
2221                 glEnable( GL_BLEND );
2222                 gl_round_box(GL_LINE_LOOP, x1, y1+3, x2, y2-3, 7.0);
2223                 glDisable( GL_LINE_SMOOTH );
2224                 glDisable( GL_BLEND );
2225                 
2226         } else {
2227                 UI_ThemeColor(colorid); // is set at TH_MENU_ITEM when pulldown opened.
2228                 glRectf(x1-1, y1+2, x2+1, y2-2);
2229         }
2230         
2231 }
2232
2233 /* ************** TEXT AND ICON DRAWING FUNCTIONS ************* */
2234
2235
2236
2237 /* draws text and icons for buttons */
2238 static void ui_draw_text_icon(uiBut *but)
2239 {
2240         float x;
2241         int len;
2242         char *cpoin;
2243         short t, pos, ch;
2244         short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw;
2245         
2246         /* check for button text label */
2247         if (but->type == ICONTEXTROW) {
2248                 ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 0);
2249         }
2250         else {
2251
2252                 /* text button selection and cursor */
2253                 if(but->editstr && but->pos != -1) {
2254                 
2255                         if ((but->selend - but->selsta) > 0) {
2256                                 /* text button selection */
2257                                 selsta_tmp = but->selsta + strlen(but->str);
2258                                 selend_tmp = but->selend + strlen(but->str);
2259                                         
2260                                 if(but->drawstr[0]!=0) {
2261                                         ch= but->drawstr[selsta_tmp];
2262                                         but->drawstr[selsta_tmp]= 0;
2263                                         
2264                                         selsta_draw = but->aspect*UI_GetStringWidth(but->font, but->drawstr+but->ofs, ui_translate_buttons()) + 3;
2265                                         
2266                                         but->drawstr[selsta_tmp]= ch;
2267                                         
2268                                         
2269                                         ch= but->drawstr[selend_tmp];
2270                                         but->drawstr[selend_tmp]= 0;
2271                                         
2272                                         selwidth_draw = but->aspect*UI_GetStringWidth(but->font, but->drawstr+but->ofs, ui_translate_buttons()) + 3;
2273                                         
2274                                         but->drawstr[selend_tmp]= ch;
2275                                         
2276                                         UI_ThemeColor(TH_BUT_TEXTFIELD_HI);
2277                                         glRects(but->x1+selsta_draw+1, but->y1+2, but->x1+selwidth_draw+1, but->y2-2);
2278                                 }
2279                         } else {
2280                                 /* text cursor */
2281                                 pos= but->pos+strlen(but->str);
2282                                 if(pos >= but->ofs) {
2283                                         if(but->drawstr[0]!=0) {
2284                                                 ch= but->drawstr[pos];
2285                                                 but->drawstr[pos]= 0;
2286                         
2287                                                 t= but->aspect*UI_GetStringWidth(but->font, but->drawstr+but->ofs, ui_translate_buttons()) + 3;
2288                                                 
2289                                                 but->drawstr[pos]= ch;
2290                                         }
2291                                         else t= 3;
2292                                         
2293                                         glColor3ub(255,0,0);
2294                                         glRects(but->x1+t, but->y1+2, but->x1+t+2, but->y2-2);
2295                                 }
2296                         }
2297                 }
2298                 
2299                 if(but->type==BUT_TOGDUAL) {
2300                         int dualset= 0;
2301                         if(but->pointype==SHO)
2302                                 dualset= BTST( *(((short *)but->poin)+1), but->bitnr);
2303                         else if(but->pointype==INT)
2304                                 dualset= BTST( *(((int *)but->poin)+1), but->bitnr);
2305                         
2306                         ui_draw_icon(but, ICON_DOT, dualset?0:-100);
2307                 }
2308                 
2309                 if(but->drawstr[0]!=0) {
2310                         int transopts;
2311                         int tog3= 0;
2312                         
2313                         // cut string in 2 parts
2314                         cpoin= strchr(but->drawstr, '|');
2315                         if(cpoin) *cpoin= 0;
2316
2317                         /* If there's an icon too (made with uiDefIconTextBut) then draw the icon
2318                         and offset the text label to accomodate it */
2319                         
2320                         if ( (but->flag & UI_HAS_ICON) && (but->flag & UI_ICON_LEFT) ) 
2321                         {
2322                                 ui_draw_icon(but, but->icon, 0);
2323                                 
2324                                 if(but->editstr || (but->flag & UI_TEXT_LEFT)) x= but->x1 + but->aspect*UI_icon_get_width(but->icon)+5.0;
2325                                 else x= (but->x1+but->x2-but->strwidth+1)/2.0;
2326                         }
2327                         else
2328                         {
2329                                 if(but->editstr || (but->flag & UI_TEXT_LEFT))
2330                                         x= but->x1+4.0;
2331                                 else if ELEM3(but->type, TOG, TOGN, TOG3)
2332                                         x= but->x1+18.0;        /* offset for checkmark */
2333                                 else
2334                                         x= (but->x1+but->x2-but->strwidth+1)/2.0;
2335                         }
2336                         
2337                         /* tog3 button exception; draws with glColor! */
2338                         if(but->type==TOG3 && (but->flag & UI_SELECT)) {
2339                                 
2340                                 if( but->pointype==CHA ) {
2341                                         if( BTST( *(but->poin+2), but->bitnr )) tog3= 1;
2342                                 }
2343                                 else if( but->pointype ==SHO ) {
2344                                         short *sp= (short *)but->poin;
2345                                         if( BTST( sp[1], but->bitnr )) tog3= 1;
2346                                 }
2347                                 
2348                                 ui_tog3_invert(but->x1,but->y1,but->x2,but->y2, tog3);
2349                                 if (tog3) glColor3ub(255, 255, 0);
2350                         }
2351                         
2352                         /* text color, with pulldown item exception */
2353                         if(tog3);       // color already set
2354                         else if(but->dt==UI_EMBOSSP) {
2355                                 if((but->flag & (UI_SELECT|UI_ACTIVE)) && but->type!=LABEL) {   // LABEL = title in pulldowns
2356                                         UI_ThemeColor(TH_MENU_TEXT_HI);
2357                                 } else {
2358                                         UI_ThemeColor(TH_MENU_TEXT);
2359                                 }
2360                         }
2361                         else {
2362                                 if(but->flag & UI_SELECT) {             
2363                                         UI_ThemeColor(TH_BUT_TEXT_HI);
2364                                 } else {
2365                                         UI_ThemeColor(TH_BUT_TEXT);
2366                                 }
2367                         }
2368
2369                         /* LABEL button exception */
2370                         if(but->type==LABEL && but->min!=0.0) UI_ThemeColor(TH_BUT_TEXT_HI);
2371                 
2372                         ui_rasterpos_safe(x, (but->y1+but->y2- 9.0)/2.0, but->aspect);
2373                         if(but->type==IDPOIN) transopts= 0;     // no translation, of course!
2374                         else transopts= ui_translate_buttons();
2375                         
2376                 #ifdef INTERNATIONAL
2377                         if (but->type == FTPREVIEW)
2378                                 FTF_DrawNewFontString (but->drawstr+but->ofs, FTF_INPUT_UTF8);
2379                         else
2380                                 UI_DrawString(but->font, but->drawstr+but->ofs, transopts);
2381                 #else
2382                         UI_DrawString(but->font, but->drawstr+but->ofs, transopts);
2383                 #endif
2384
2385                         /* part text right aligned */
2386                         if(cpoin) {
2387                                 len= UI_GetStringWidth(but->font, cpoin+1, ui_translate_buttons());
2388                                 ui_rasterpos_safe( but->x2 - len*but->aspect-3, (but->y1+but->y2- 9.0)/2.0, but->aspect);
2389                                 UI_DrawString(but->font, cpoin+1, ui_translate_buttons());
2390                                 *cpoin= '|';
2391                         }
2392                 }
2393                 /* if there's no text label, then check to see if there's an icon only and draw it */
2394                 else if( but->flag & UI_HAS_ICON ) {
2395                         ui_draw_icon(but, (BIFIconID) (but->icon+but->iconadd), 0);
2396                 }
2397         }
2398 }
2399
2400 static void ui_draw_but_COL(uiBut *but)
2401 {
2402         float *fp;
2403         char colr, colg, colb;
2404         
2405         if( but->pointype==FLO ) {
2406                 fp= (float *)but->poin;
2407                 colr= floor(255.0*fp[0]+0.5);
2408                 colg= floor(255.0*fp[1]+0.5);
2409                 colb= floor(255.0*fp[2]+0.5);
2410         }
2411         else {
2412                 char *cp= (char *)but->poin;
2413                 colr= cp[0];
2414                 colg= cp[1];
2415                 colb= cp[2];
2416         }
2417         
2418         /* exception... hrms, but can't simply use the emboss callback for this now. */
2419         /* this button type needs review, and nice integration with rest of API here */
2420         /* XXX 2.50 bad U global access */
2421         if(but->embossfunc == ui_draw_round) {
2422                 char *cp= UI_ThemeGetColorPtr(U.themes.first, 0, TH_CUSTOM);
2423                 cp[0]= colr; cp[1]= colg; cp[2]= colb;
2424                 but->flag &= ~UI_SELECT;
2425                 but->embossfunc(but->type, TH_CUSTOM, but->aspect, but->x1, but->y1, but->x2, but->y2, but->flag);
2426         }
2427         else
2428         {
2429                 
2430                 glColor3ub(colr,  colg,  colb);
2431                 glRectf((but->x1), (but->y1), (but->x2), (but->y2));
2432                 glColor3ub(0,  0,  0);
2433                 fdrawbox((but->x1), (but->y1), (but->x2), (but->y2));
2434         }
2435 }
2436
2437 /* draws in resolution of 20x4 colors */
2438 static void ui_draw_but_HSVCUBE(uiBut *but)
2439 {
2440         int a;
2441         float h,s,v;
2442         float dx, dy, sx1, sx2, sy, x, y;
2443         float col0[4][3];       // left half, rect bottom to top
2444         float col1[4][3];       // right half, rect bottom to top
2445         
2446         h= but->hsv[0];
2447         s= but->hsv[1];
2448         v= but->hsv[2];
2449         
2450         /* draw series of gouraud rects */
2451         glShadeModel(GL_SMOOTH);
2452         
2453         if(but->a1==0) {        // H and V vary
2454                 hsv_to_rgb(0.0, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2455                 hsv_to_rgb(0.0, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
2456                 hsv_to_rgb(0.0, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
2457                 hsv_to_rgb(0.0, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
2458                 x= h; y= v;
2459         }
2460         else if(but->a1==1) {   // H and S vary
2461                 hsv_to_rgb(0.0, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
2462                 hsv_to_rgb(0.0, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
2463                 hsv_to_rgb(0.0, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
2464                 hsv_to_rgb(0.0, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
2465                 x= h; y= s;
2466         }
2467         else if(but->a1==2) {   // S and V vary
2468                 hsv_to_rgb(h, 0.0, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2469                 hsv_to_rgb(h, 0.333, 0.0, &col1[1][0], &col1[1][1], &col1[1][2]);
2470                 hsv_to_rgb(h, 0.666, 0.0, &col1[2][0], &col1[2][1], &col1[2][2]);
2471                 hsv_to_rgb(h, 1.0, 0.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
2472                 x= v; y= s;
2473         }
2474         else {          // only hue slider
2475                 hsv_to_rgb(0.0, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2476                 VECCOPY(col1[1], col1[0]);
2477                 VECCOPY(col1[2], col1[0]);
2478                 VECCOPY(col1[3], col1[0]);
2479                 x= h; y= 0.5;
2480         }
2481         
2482         for(dx=0.0; dx<1.0; dx+= 0.05) {
2483                 // previous color
2484                 VECCOPY(col0[0], col1[0]);
2485                 VECCOPY(col0[1], col1[1]);
2486                 VECCOPY(col0[2], col1[2]);
2487                 VECCOPY(col0[3], col1[3]);
2488
2489                 // new color
2490                 if(but->a1==0) {        // H and V vary
2491                         hsv_to_rgb(dx, s, 0.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2492                         hsv_to_rgb(dx, s, 0.333, &col1[1][0], &col1[1][1], &col1[1][2]);
2493                         hsv_to_rgb(dx, s, 0.666, &col1[2][0], &col1[2][1], &col1[2][2]);
2494                         hsv_to_rgb(dx, s, 1.0,   &col1[3][0], &col1[3][1], &col1[3][2]);
2495                 }
2496                 else if(but->a1==1) {   // H and S vary
2497                         hsv_to_rgb(dx, 0.0, v,   &col1[0][0], &col1[0][1], &col1[0][2]);
2498                         hsv_to_rgb(dx, 0.333, v, &col1[1][0], &col1[1][1], &col1[1][2]);
2499                         hsv_to_rgb(dx, 0.666, v, &col1[2][0], &col1[2][1], &col1[2][2]);
2500                         hsv_to_rgb(dx, 1.0, v,   &col1[3][0], &col1[3][1], &col1[3][2]);
2501                 }
2502                 else if(but->a1==2) {   // S and V vary
2503                         hsv_to_rgb(h, 0.0, dx,   &col1[0][0], &col1[0][1], &col1[0][2]);
2504                         hsv_to_rgb(h, 0.333, dx, &col1[1][0], &col1[1][1], &col1[1][2]);
2505                         hsv_to_rgb(h, 0.666, dx, &col1[2][0], &col1[2][1], &col1[2][2]);
2506                         hsv_to_rgb(h, 1.0, dx,   &col1[3][0], &col1[3][1], &col1[3][2]);
2507                 }
2508                 else {  // only H
2509                         hsv_to_rgb(dx, 1.0, 1.0,   &col1[0][0], &col1[0][1], &col1[0][2]);
2510                         VECCOPY(col1[1], col1[0]);
2511                         VECCOPY(col1[2], col1[0]);
2512                         VECCOPY(col1[3], col1[0]);
2513                 }
2514                 
2515                 // rect
2516                 sx1= but->x1 + dx*(but->x2-but->x1);
2517                 sx2= but->x1 + (dx+0.05)*(but->x2-but->x1);
2518                 sy= but->y1;
2519                 dy= (but->y2-but->y1)/3.0;
2520                 
2521                 glBegin(GL_QUADS);
2522                 for(a=0; a<3; a++, sy+=dy) {
2523                         glColor3fv(col0[a]);
2524                         glVertex2f(sx1, sy);
2525
2526                         glColor3fv(col1[a]);
2527                         glVertex2f(sx2, sy);
2528                         
2529                         glColor3fv(col1[a+1]);
2530                         glVertex2f(sx2, sy+dy);
2531                         
2532                         glColor3fv(col0[a+1]);
2533                         glVertex2f(sx1, sy+dy);
2534                 }
2535                 glEnd();
2536         }
2537
2538         glShadeModel(GL_FLAT);
2539
2540         /* cursor */
2541         x= but->x1 + x*(but->x2-but->x1);
2542         y= but->y1 + y*(but->y2-but->y1);
2543         CLAMP(x, but->x1+3.0, but->x2-3.0);
2544         CLAMP(y, but->y1+3.0, but->y2-3.0);
2545         
2546         fdrawXORcirc(x, y, 3.1);
2547
2548         /* outline */
2549         glColor3ub(0,  0,  0);
2550         fdrawbox((but->x1), (but->y1), (but->x2), (but->y2));
2551 }
2552
2553 #ifdef INTERNATIONAL
2554 static void ui_draw_but_CHARTAB(uiBut *but)
2555 {
2556         /* XXX 2.50 bad global access */
2557 #if 0
2558         /* Some local variables */
2559         float sx, sy, ex, ey;
2560         float width, height;
2561         float butw, buth;
2562         int x, y, cs;
2563         wchar_t wstr[2];
2564         unsigned char ustr[16];
2565         PackedFile *pf;
2566         int result = 0;
2567         int charmax = G.charmax;
2568         
2569         /* <builtin> font in use. There are TTF <builtin> and non-TTF <builtin> fonts */
2570         if(!strcmp(G.selfont->name, "<builtin>"))
2571         {
2572                 if(G.ui_international == TRUE)
2573                 {
2574                         charmax = 0xff;
2575                 }
2576                 else
2577                 {
2578                         charmax = 0xff;
2579                 }
2580         }
2581
2582         /* Category list exited without selecting the area */
2583         if(G.charmax == 0)
2584                 charmax = G.charmax = 0xffff;
2585
2586         /* Calculate the size of the button */
2587         width = abs(but->x2 - but->x1);
2588         height = abs(but->y2 - but->y1);
2589         
2590         butw = floor(width / 12);
2591         buth = floor(height / 6);
2592         
2593         /* Initialize variables */
2594         sx = but->x1;
2595         ex = but->x1 + butw;
2596         sy = but->y1 + height - buth;
2597         ey = but->y1 + height;
2598
2599         cs = G.charstart;
2600
2601         /* Set the font, in case it is not <builtin> font */
2602         if(G.selfont && strcmp(G.selfont->name, "<builtin>"))
2603         {
2604                 char tmpStr[256];
2605
2606                 // Is the font file packed, if so then use the packed file
2607                 if(G.selfont->packedfile)
2608                 {
2609                         pf = G.selfont->packedfile;             
2610                         FTF_SetFont(pf->data, pf->size, 14.0);
2611                 }
2612                 else
2613                 {
2614                         int err;
2615
2616                         strcpy(tmpStr, G.selfont->name);
2617                         BLI_convertstringcode(tmpStr, G.sce);
2618                         err = FTF_SetFont((unsigned char *)tmpStr, 0, 14.0);
2619                 }
2620         }
2621         else
2622         {
2623                 if(G.ui_international == TRUE)
2624                 {
2625                         FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 14.0);
2626                 }
2627         }
2628
2629         /* Start drawing the button itself */
2630         glShadeModel(GL_SMOOTH);
2631
2632         glColor3ub(200,  200,  200);
2633         glRectf((but->x1), (but->y1), (but->x2), (but->y2));
2634
2635         glColor3ub(0,  0,  0);
2636         for(y = 0; y < 6; y++)
2637         {
2638                 // Do not draw more than the category allows
2639                 if(cs > charmax) break;
2640
2641                 for(x = 0; x < 12; x++)
2642                 {
2643                         // Do not draw more than the category allows
2644                         if(cs > charmax) break;
2645
2646                         // Draw one grid cell
2647                         glBegin(GL_LINE_LOOP);
2648                                 glVertex2f(sx, sy);
2649                                 glVertex2f(ex, sy);
2650                                 glVertex2f(ex, ey);
2651                                 glVertex2f(sx, ey);                             
2652                         glEnd();        
2653
2654                         // Draw character inside the cell
2655                         memset(wstr, 0, sizeof(wchar_t)*2);
2656                         memset(ustr, 0, 16);
2657
2658                         // Set the font to be either unicode or <builtin>                               
2659                         wstr[0] = cs;
2660                         if(strcmp(G.selfont->name, "<builtin>"))
2661                         {
2662                                 wcs2utf8s((char *)ustr, (wchar_t *)wstr);
2663                         }
2664                         else
2665                         {
2666                                 if(G.ui_international == TRUE)
2667                                 {
2668                                         wcs2utf8s((char *)ustr, (wchar_t *)wstr);
2669                                 }
2670                                 else
2671                                 {
2672                                         ustr[0] = cs;
2673                                         ustr[1] = 0;
2674                                 }
2675                         }
2676
2677                         if((G.selfont && strcmp(G.selfont->name, "<builtin>")) || (G.selfont && !strcmp(G.selfont->name, "<builtin>") && G.ui_international == TRUE))
2678                         {
2679                                 float wid;
2680                                 float llx, lly, llz, urx, ury, urz;
2681                                 float dx, dy;
2682                                 float px, py;
2683         
2684                                 // Calculate the position
2685                                 wid = FTF_GetStringWidth((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
2686                                 FTF_GetBoundingBox((char *) ustr, &llx,&lly,&llz,&urx,&ury,&urz, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
2687                                 dx = urx-llx;
2688                                 dy = ury-lly;
2689
2690                                 // This isn't fully functional since the but->aspect isn't working like I suspected
2691                                 px = sx + ((butw/but->aspect)-dx)/2;
2692                                 py = sy + ((buth/but->aspect)-dy)/2;
2693
2694                                 // Set the position and draw the character
2695                                 ui_rasterpos_safe(px, py, but->aspect);
2696                                 FTF_DrawString((char *) ustr, FTF_USE_GETTEXT | FTF_INPUT_UTF8);
2697                         }
2698                         else
2699                         {
2700                                 ui_rasterpos_safe(sx + butw/2, sy + buth/2, but->aspect);
2701                                 UI_DrawString(but->font, (char *) ustr, 0);
2702                         }
2703         
2704                         // Calculate the next position and character
2705                         sx += butw; ex +=butw;
2706                         cs++;
2707                 }
2708                 /* Add the y position and reset x position */
2709                 sy -= buth; 
2710                 ey -= buth;
2711                 sx = but->x1;
2712                 ex = but->x1 + butw;
2713         }       
2714         glShadeModel(GL_FLAT);
2715
2716         /* Return Font Settings to original */
2717         if(U.fontsize && U.fontname[0])
2718         {
2719                 result = FTF_SetFont((unsigned char *)U.fontname, 0, U.fontsize);
2720         }
2721         else if (U.fontsize)
2722         {
2723                 result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, U.fontsize);
2724         }
2725
2726         if (result == 0)
2727         {
2728                 result = FTF_SetFont((unsigned char *) datatoc_bfont_ttf, datatoc_bfont_ttf_size, 11);
2729         }
2730         
2731         /* resets the font size */
2732         if(G.ui_international == TRUE)
2733         {
2734                 uiSetCurFont(but->block, UI_HELV);
2735         }
2736 #endif
2737 }
2738
2739 #endif // INTERNATIONAL
2740
2741 static void ui_draw_but_COLORBAND(uiBut *but)
2742 {
2743         ColorBand *coba;
2744         CBData *cbd;
2745         float x1, y1, sizex, sizey;
2746         float dx, v3[2], v1[2], v2[2], v1a[2], v2a[2];
2747         int a;
2748                 
2749         coba= (ColorBand *)(but->editcoba? but->editcoba: but->poin);
2750         if(coba==NULL) return;
2751         
2752         x1= but->x1;
2753         y1= but->y1;
2754         sizex= but->x2-x1;
2755         sizey= but->y2-y1;
2756         
2757         /* first background, to show tranparency */
2758         dx= sizex/12.0;
2759         v1[0]= x1;
2760         for(a=0; a<12; a++) {
2761                 if(a & 1) glColor3f(0.3, 0.3, 0.3); else glColor3f(0.8, 0.8, 0.8);
2762                 glRectf(v1[0], y1, v1[0]+dx, y1+0.5*sizey);
2763                 if(a & 1) glColor3f(0.8, 0.8, 0.8); else glColor3f(0.3, 0.3, 0.3);
2764                 glRectf(v1[0], y1+0.5*sizey, v1[0]+dx, y1+sizey);
2765                 v1[0]+= dx;
2766         }
2767         
2768         glShadeModel(GL_SMOOTH);
2769         glEnable(GL_BLEND);
2770         
2771         cbd= coba->data;
2772         
2773         v1[0]= v2[0]= x1;
2774         v1[1]= y1;
2775         v2[1]= y1+sizey;
2776         
2777         glBegin(GL_QUAD_STRIP);
2778         
2779         glColor4fv( &cbd->r );
2780         glVertex2fv(v1); glVertex2fv(v2);
2781         
2782         for(a=0; a<coba->tot; a++, cbd++) {
2783                 
2784                 v1[0]=v2[0]= x1+ cbd->pos*sizex;
2785                 
2786                 glColor4fv( &cbd->r );
2787                 glVertex2fv(v1); glVertex2fv(v2);
2788         }
2789         
2790         v1[0]=v2[0]= x1+ sizex;
2791         glVertex2fv(v1); glVertex2fv(v2);
2792         
2793         glEnd();
2794         glShadeModel(GL_FLAT);
2795         glDisable(GL_BLEND);
2796         
2797         /* outline */
2798         v1[0]= x1; v1[1]= y1;
2799         
2800         cpack(0x0);
2801         glBegin(GL_LINE_LOOP);
2802         glVertex2fv(v1);
2803         v1[0]+= sizex;
2804         glVertex2fv(v1);
2805         v1[1]+= sizey;
2806         glVertex2fv(v1);
2807         v1[0]-= sizex;
2808         glVertex2fv(v1);
2809         glEnd();
2810         
2811         
2812         /* help lines */
2813         v1[0]= v2[0]=v3[0]= x1;
2814         v1[1]= y1;
2815         v1a[1]= y1+0.25*sizey;
2816         v2[1]= y1+0.5*sizey;
2817         v2a[1]= y1+0.75*sizey;
2818         v3[1]= y1+sizey;
2819         
2820         
2821         cbd= coba->data;
2822         glBegin(GL_LINES);
2823         for(a=0; a<coba->tot; a++, cbd++) {
2824                 v1[0]=v2[0]=v3[0]=v1a[0]=v2a[0]= x1+ cbd->pos*sizex;
2825                 
2826                 if(a==coba->cur) {
2827                         glColor3ub(0, 0, 0);
2828                         glVertex2fv(v1);
2829                         glVertex2fv(v3);
2830                         glEnd();
2831                         
2832                         setlinestyle(2);
2833                         glBegin(GL_LINES);
2834                         glColor3ub(255, 255, 255);
2835                         glVertex2fv(v1);
2836                         glVertex2fv(v3);
2837                         glEnd();
2838                         setlinestyle(0);
2839                         glBegin(GL_LINES);
2840                         
2841                         /* glColor3ub(0, 0, 0);
2842                         glVertex2fv(v1);
2843                         glVertex2fv(v1a);
2844                         glColor3ub(255, 255, 255);
2845                         glVertex2fv(v1a);
2846                         glVertex2fv(v2);
2847                         glColor3ub(0, 0, 0);
2848                         glVertex2fv(v2);
2849                         glVertex2fv(v2a);
2850                         glColor3ub(255, 255, 255);
2851                         glVertex2fv(v2a);
2852                         glVertex2fv(v3);
2853                         */
2854                 }
2855                 else {
2856                         glColor3ub(0, 0, 0);
2857                         glVertex2fv(v1);
2858                         glVertex2fv(v2);
2859                         
2860                         glColor3ub(255, 255, 255);
2861                         glVertex2fv(v2);
2862                         glVertex2fv(v3);
2863                 }       
2864         }
2865         glEnd();
2866 }
2867
2868 static void ui_draw_but_NORMAL(uiBut *but)
2869 {
2870         static GLuint displist=0;
2871         int a, old[8];
2872         GLfloat diff[4], diffn[4]={1.0f, 1.0f, 1.0f, 1.0f};
2873         float vec0[4]={0.0f, 0.0f, 0.0f, 0.0f};
2874         float dir[4], size;
2875         
2876         /* store stuff */
2877         glGetMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
2878                 
2879         /* backdrop */
2880         UI_ThemeColor(TH_BUT_NEUTRAL);
2881         uiSetRoundBox(15);
2882         gl_round_box(GL_POLYGON, but->x1, but->y1, but->x2, but->y2, 5.0f);
2883         
2884         /* sphere color */
2885         glMaterialfv(GL_FRONT, GL_DIFFUSE, diffn);
2886         glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
2887         
2888         /* disable blender light */
2889         for(a=0; a<8; a++) {
2890                 old[a]= glIsEnabled(GL_LIGHT0+a);
2891                 glDisable(GL_LIGHT0+a);
2892         }
2893         
2894         /* own light */
2895         glEnable(GL_LIGHT7);
2896         glEnable(GL_LIGHTING);
2897         
2898         VECCOPY(dir, (float *)but->poin);
2899         dir[3]= 0.0f;   /* glLight needs 4 args, 0.0 is sun */
2900         glLightfv(GL_LIGHT7, GL_POSITION, dir); 
2901         glLightfv(GL_LIGHT7, GL_DIFFUSE, diffn); 
2902         glLightfv(GL_LIGHT7, GL_SPECULAR, vec0); 
2903         glLightf(GL_LIGHT7, GL_CONSTANT_ATTENUATION, 1.0f);
2904         glLightf(GL_LIGHT7, GL_LINEAR_ATTENUATION, 0.0f);
2905         
2906         /* transform to button */
2907         glPushMatrix();
2908         glTranslatef(but->x1 + 0.5f*(but->x2-but->x1), but->y1+ 0.5f*(but->y2-but->y1), 0.0f);
2909         size= (but->x2-but->x1)/200.f;
2910         glScalef(size, size, size);
2911                          
2912         if(displist==0) {
2913                 GLUquadricObj   *qobj;
2914                 
2915                 displist= glGenLists(1);
2916                 glNewList(displist, GL_COMPILE_AND_EXECUTE);
2917                 
2918                 qobj= gluNewQuadric();
2919                 gluQuadricDrawStyle(qobj, GLU_FILL); 
2920                 glShadeModel(GL_SMOOTH);
2921                 gluSphere( qobj, 100.0, 32, 24);
2922                 glShadeModel(GL_FLAT);
2923                 gluDeleteQuadric(qobj);  
2924                 
2925                 glEndList();
2926         }
2927         else glCallList(displist);
2928         
2929         /* restore */
2930         glPopMatrix();
2931         glDisable(GL_LIGHTING);
2932         glDisable(GL_CULL_FACE);
2933         glMaterialfv(GL_FRONT, GL_DIFFUSE, diff); 
2934         
2935         glDisable(GL_LIGHT7);
2936         
2937         /* enable blender light */
2938         for(a=0; a<8; a++) {
2939                 if(old[a])
2940                         glEnable(GL_LIGHT0+a);
2941         }
2942 }
2943
2944 static void ui_draw_but_curve_grid(uiBut *but, float zoomx, float zoomy, float offsx, float offsy, float step)
2945 {
2946         float dx, dy, fx, fy;
2947         
2948         glBegin(GL_LINES);
2949         dx= step*zoomx;
2950         fx= but->x1 + zoomx*(-offsx);
2951         if(fx > but->x1) fx -= dx*( floor(fx-but->x1));
2952         while(fx < but->x2) {
2953                 glVertex2f(fx, but->y1); 
2954                 glVertex2f(fx, but->y2);
2955                 fx+= dx;
2956         }
2957         
2958         dy= step*zoomy;
2959         fy= but->y1 + zoomy*(-offsy);
2960         if(fy > but->y1) fy -= dy*( floor(fy-but->y1));
2961         while(fy < but->y2) {
2962                 glVertex2f(but->x1, fy); 
2963                 glVertex2f(but->x2, fy);
2964                 fy+= dy;
2965         }
2966         glEnd();
2967         
2968 }
2969
2970 static void ui_draw_but_CURVE(uiBut *but)
2971 {
2972         CurveMapping *cumap;
2973         CurveMap *cuma;
2974         CurveMapPoint *cmp;
2975         float fx, fy, dx, dy, fac[2], zoomx, zoomy, offsx, offsy;
2976         GLint scissor[4];
2977         int a;
2978
2979         cumap= (CurveMapping *)(but->editcumap? but->editcumap: but->poin);
2980         cuma= cumap->cm+cumap->cur;
2981         
2982         /* need scissor test, curve can draw outside of boundary */
2983         glGetIntegerv(GL_VIEWPORT, scissor);
2984         fx= but->x1; fy= but->y1;
2985         /* XXX 2.50 need context: ui_graphics_to_window(but->win, &fx, &fy); */
2986         dx= but->x2; dy= but->y2;
2987         /* XXX 2.50 need context: ui_graphics_to_window(but->win, &dx, &dy); */
2988         //glScissor((int)floor(fx), (int)floor(fy), (int)ceil(dx-fx), (int)ceil(dy-fy));
2989         
2990         /* calculate offset and zoom */
2991         zoomx= (but->x2-but->x1-2.0*but->aspect)/(cumap->curr.xmax - cumap->curr.xmin);
2992         zoomy= (but->y2-but->y1-2.0*but->aspect)/(cumap->curr.ymax - cumap->curr.ymin);
2993         offsx= cumap->curr.xmin-but->aspect/zoomx;
2994         offsy= cumap->curr.ymin-but->aspect/zoomy;
2995         
2996         /* backdrop */
2997         if(cumap->flag & CUMA_DO_CLIP) {
2998                 UI_ThemeColorShade(TH_BUT_NEUTRAL, -20);
2999                 glRectf(but->x1, but->y1, but->x2, but->y2);
3000                 UI_ThemeColor(TH_BUT_NEUTRAL);
3001                 glRectf(but->x1 + zoomx*(cumap->clipr.xmin-offsx),
3002                                 but->y1 + zoomy*(cumap->clipr.ymin-offsy),
3003                                 but->x1 + zoomx*(cumap->clipr.xmax-offsx),
3004                                 but->y1 + zoomy*(cumap->clipr.ymax-offsy));
3005         }
3006         else {
3007                 UI_ThemeColor(TH_BUT_NEUTRAL);
3008                 glRectf(but->x1, but->y1, but->x2, but->y2);
3009         }
3010         
3011         /* grid, every .25 step */
3012         UI_ThemeColorShade(TH_BUT_NEUTRAL, -16);
3013         ui_draw_but_curve_grid(but, zoomx, zoomy, offsx, offsy, 0.25f);
3014         /* grid, every 1.0 step */
3015         UI_ThemeColorShade(TH_BUT_NEUTRAL, -24);
3016         ui_draw_but_curve_grid(but, zoomx, zoomy, offsx, offsy, 1.0f);
3017         /* axes */
3018         UI_ThemeColorShade(TH_BUT_NEUTRAL, -50);
3019         glBegin(GL_LINES);
3020         glVertex2f(but->x1, but->y1 + zoomy*(-offsy));
3021         glVertex2f(but->x2, but->y1 + zoomy*(-offsy));
3022         glVertex2f(but->x1 + zoomx*(-offsx), but->y1);
3023         glVertex2f(but->x1 + zoomx*(-offsx), but->y2);
3024         glEnd();
3025         
3026         /* cfra option */
3027         /* XXX 2.48