1 /* Glide - a cairo based GTK+ engine
2  * Copyright (C) 2006 Andrew Johnson <acjgenius@earthlink.net>
3  * Copyright (C) 2006-2007 Benjamin Berg <benjamin@sipsolutions.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  * Project contact: <gnome-themes-list@gnome.org>
20  *
21  */
22 
23 
24 #include <string.h>
25 #include "glide_gtk2_engine.h"
26 #include "glide_gtk2_support.h"
27 #include "glide_gtk2_drawing.h"
28 
29 /***********************************************
30  * glide_draw_vline -
31  *
32  *   the Function used to draw horizontal spacers.
33  ***********************************************/
34 void
glide_draw_hline(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x1,gint x2,gint y)35 glide_draw_hline (GtkStyle * style,
36 	    GdkWindow * window,
37 	    GtkStateType state_type,
38 	    GdkRectangle * area,
39 	    GtkWidget * widget,
40 	    const gchar * detail,
41             gint x1,
42             gint x2,
43             gint y)
44 {
45   GlideStyle *glide_style = GLIDE_STYLE (style);
46   cairo_t *canvas;
47 
48   CHECK_ARGS
49 
50   canvas = ge_gdk_drawable_to_cairo (window, area);
51 
52   do_glide_draw_line(canvas,
53                        &glide_style->color_cube.dark[state_type],
54                        &glide_style->color_cube.light[state_type],
55                        area,
56                        x1, x2, y,
57                        TRUE);
58 
59   cairo_destroy(canvas);
60 }
61 
62 /***********************************************
63  * glide_draw_vline -
64  *
65  *   the Function used to draw vertical spacers.
66  ***********************************************/
67 void
glide_draw_vline(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint y1,gint y2,gint x)68 glide_draw_vline (GtkStyle * style,
69 	    GdkWindow * window,
70 	    GtkStateType state_type,
71 	    GdkRectangle * area,
72 	    GtkWidget * widget,
73 	    const gchar * detail,
74             gint y1,
75             gint y2,
76             gint x)
77 {
78   GlideStyle *glide_style = GLIDE_STYLE (style);
79   cairo_t *canvas;
80 
81   if (ge_is_combo_box(widget, FALSE) && (!ge_is_combo_box_entry(widget)))
82     return;
83 
84   CHECK_ARGS
85 
86   canvas = ge_gdk_drawable_to_cairo (window, area);
87 
88   do_glide_draw_line(canvas,
89                        &glide_style->color_cube.dark[state_type],
90                        &glide_style->color_cube.light[state_type],
91                        area,
92                        y1, y2, x,
93                        FALSE);
94 
95   cairo_destroy(canvas);
96 }
97 
98 /***********************************************
99  * glide_draw_check -
100  *
101  *   the Function used to draw all check boxes.
102  ***********************************************/
103 void
glide_draw_check(GtkStyle * style,GdkWindow * window,GtkStateType state,GtkShadowType shadow,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)104 glide_draw_check (GtkStyle * style,
105 	    GdkWindow * window,
106 	    GtkStateType state,
107 	    GtkShadowType shadow,
108 	    GdkRectangle * area,
109 	    GtkWidget * widget,
110 	    const gchar * detail,
111             gint x,
112             gint y,
113             gint width,
114             gint height)
115 {
116 	GlideStyle *glide_style = GLIDE_STYLE (style);
117 	cairo_t *canvas;
118 	gboolean inconsistent;
119 
120 	CHECK_ARGS
121 	SANITIZE_SIZE
122 
123 	if (GE_IS_CHECK_MENU_ITEM(widget))
124 	{
125 		x -= 1;
126 		y -= 1;
127 		width += 2;
128 		height += 2;
129 	}
130 	else if (GE_IS_CELL_RENDERER_TOGGLE(widget) || CHECK_DETAIL(detail, "cellcheck"))
131 	{
132 		x -= 1;
133 		y -= 1;
134 		width += 2;
135 		height += 2;
136 	}
137 
138 
139 	canvas = ge_gdk_drawable_to_cairo (window, area);
140 
141 	ge_cairo_set_color(canvas, &glide_style->color_cube.base[state]);
142 
143 	cairo_rectangle(canvas, x, y, width - 1, height - 1);
144 
145 	cairo_fill(canvas);
146 
147 	inconsistent = shadow == GTK_SHADOW_ETCHED_IN;
148 
149 	if ((shadow == GTK_SHADOW_IN) || (inconsistent))
150 	{
151 		if (inconsistent)
152 		{
153 			gdouble radius = (MIN(width, height)/2) - 2;
154 			gdouble line_width = (radius/2.0);
155 
156 			cairo_set_line_cap(canvas, CAIRO_LINE_CAP_SQUARE);
157 			cairo_set_line_width (canvas, floor(line_width));
158 
159 			cairo_move_to(canvas, x + floor(width/2 - radius + line_width), y + floor(height/2.0));
160 			cairo_line_to(canvas, x + ceil(width/2 + radius - line_width), y + floor(height/2.0));
161 
162 			if (state==GTK_STATE_INSENSITIVE)
163 			{
164 				ge_cairo_set_color(canvas, &glide_style->color_cube.dark[state]);
165 			}
166 			else
167 			{
168 				ge_cairo_set_color(canvas, &glide_style->color_cube.text[state]);
169 			}
170 
171 			cairo_stroke (canvas);
172 		}
173 		else
174 		{
175 			if (state==GTK_STATE_INSENSITIVE)
176 			{
177 				do_glide_draw_check (canvas, &glide_style->color_cube.dark[state],
178 								x + 2, y + 2, width - 4, height - 4);
179 			}
180 			else
181 			{
182 				do_glide_draw_check (canvas, &glide_style->color_cube.text[state],
183 								x + 2, y + 2, width - 4, height - 4);
184 			}
185 		}
186 	}
187 
188 	if (state!=GTK_STATE_PRELIGHT)
189 		state = GTK_STATE_NORMAL;
190 
191 	do_glide_draw_border(canvas, &glide_style->color_cube.bg[state],
192 				GLIDE_BEVEL_STYLE_SMOOTHER, GLIDE_BORDER_TYPE_IN,
193 				x, y, width, height);
194 
195 
196 	cairo_destroy(canvas);
197 }
198 
199 /***********************************************
200  * glide_draw_option -
201  *
202  *   the Function used to draw all Option boxes
203  ***********************************************/
204 void
glide_draw_option(GtkStyle * style,GdkWindow * window,GtkStateType state,GtkShadowType shadow,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)205 glide_draw_option (GtkStyle * style,
206 	     GdkWindow * window,
207 	     GtkStateType state,
208 	     GtkShadowType shadow,
209 	     GdkRectangle * area,
210 	     GtkWidget * widget,
211 	     const gchar * detail,
212              gint x,
213              gint y,
214              gint width,
215              gint height)
216 {
217 	GlideCheckState check_state;
218 
219 	GlideStyle *glide_style;
220 
221 	CairoColor *base;
222 	CairoColor *fill_color;
223 	CairoColor *check_color;
224 
225 	GlideBevelStyle bevel_style;
226 	GlideBorderType border_type;
227 
228 	cairo_t *canvas;
229 
230 	/***********************************************/
231 	/* GTK Sanity Checks                           */
232 	/***********************************************/
233 	CHECK_ARGS
234 	SANITIZE_SIZE
235 
236 
237 	/***********************************************/
238 	/* GTK Special Cases - adjust Size/Offset      */
239 	/***********************************************/
240 	if (GE_IS_CELL_RENDERER_TOGGLE(widget) || CHECK_DETAIL(detail, "cellradio"))
241         {
242 		x -= 1;
243 		y -= 1;
244 		width += 2;
245 		height += 2;
246 	}
247 
248 	switch (shadow)
249 	{
250 	case GTK_SHADOW_ETCHED_IN:
251 		check_state = GLIDE_CHECK_INCONSISTENT;
252 		break;
253 	case GTK_SHADOW_IN:
254 		check_state = GLIDE_CHECK_ON;
255 		break;
256 	case GTK_SHADOW_OUT:
257 		check_state = GLIDE_CHECK_OFF;
258 		break;
259 	default:
260 		g_return_if_reached ();
261 	}
262 
263 	/***********************************************/
264 	/* Appearance                                  */
265 	/***********************************************/
266 
267 
268 		/***********************************************/
269 		/* Colors                                      */
270 		/***********************************************/
271 		glide_style = GLIDE_STYLE (style);
272 
273 		base = &glide_style->color_cube.bg[state];
274 		fill_color = &glide_style->color_cube.base[state];
275 		check_color = &glide_style->color_cube.text[state];
276 
277 		if (state == GTK_STATE_INSENSITIVE)
278 		{
279 			check_color = &glide_style->color_cube.dark[state];
280 		}
281 
282 
283 		/***********************************************/
284 		/* Style                                       */
285 		/***********************************************/
286 		bevel_style = GLIDE_BEVEL_STYLE_SMOOTHER;
287 		border_type = GLIDE_BORDER_TYPE_IN;
288 
289 	/***********************************************/
290 	/* Draw Option                                 */
291 	/***********************************************/
292 	canvas = ge_gdk_drawable_to_cairo (window, area);
293 
294 	do_glide_draw_round_option(canvas, base, fill_color, check_color,
295 					bevel_style, border_type, check_state,
296 					x, y, width, height);
297 
298 	cairo_destroy(canvas);
299 }
300 
301 /***********************************************
302  * glide_draw_arrow -
303  *
304  *   the Function used to draw all arrows
305  *
306  *   Glide Arrows have 2 looks, Normal
307  *   & Insensitive
308  ***********************************************/
309 void
glide_draw_arrow(GtkStyle * style,GdkWindow * window,GtkStateType state,GtkShadowType shadow,GdkRectangle * area,GtkWidget * widget,const gchar * detail,GtkArrowType arrow_type,gboolean fill,gint x,gint y,gint width,gint height)310 glide_draw_arrow (GtkStyle * style,
311 	    GdkWindow * window,
312 	    GtkStateType state,
313 	    GtkShadowType shadow,
314 	    GdkRectangle * area,
315 	    GtkWidget * widget,
316 	    const gchar * detail,
317 	    GtkArrowType arrow_type,
318 	    gboolean fill,
319             gint x,
320             gint y,
321             gint width,
322             gint height)
323 {
324 	gboolean button_in;
325 	gint child_offset_x, child_offset_y;
326 
327 	GlideStyle *glide_style;
328 
329 	cairo_t *canvas;
330 
331 	/***********************************************/
332 	/* GTK Sanity Checks                           */
333 	/***********************************************/
334 	CHECK_ARGS
335 	SANITIZE_SIZE
336 
337 	/***********************************************/
338 	/* GTK Arrow Special Cases - adjust Size/Offset*/
339 	/***********************************************/
340 	button_in = (shadow == GTK_SHADOW_IN);
341 	child_offset_x = child_offset_y = 1;
342 
343 	if ((ge_is_combo_box(widget, FALSE)
344 			&& !ge_is_combo_box_entry(widget))
345 		|| (CHECK_DETAIL (detail, "spinbutton")))
346 	{
347 		return;
348  	}
349 
350 	if ((CHECK_DETAIL (detail, "vscrollbar"))
351 		|| (CHECK_DETAIL (detail, "hscrollbar"))
352 		|| GE_IS_SCROLLBAR(widget))
353 	{
354 		if (arrow_type == GTK_ARROW_LEFT)
355 		{
356 			x -= 1;
357 		}
358 
359 		if (arrow_type == GTK_ARROW_UP)
360 		{
361 			y -= 1;
362 		}
363 
364 		width += 1;
365 		height += 1;
366 
367 		if (button_in)
368 		{
369 			/* Arrows offset down/right on button press */
370 			x += child_offset_x;
371 			y += child_offset_y;
372 		}
373 	}
374 
375 
376 	if (CHECK_DETAIL (detail, "spinbutton_arrow"))
377 	{
378 		x += 2;
379 		y += 2;
380 		width -= 4;
381 		height -= 4;
382 
383 		if (button_in)
384 		{
385 			/* Arrows offset down/right on button press */
386 			x += child_offset_x;
387 			y += child_offset_y;
388 		}
389 	}
390 
391 	if (ge_is_in_combo_box (widget))
392 	{
393 		if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
394 		{
395 			x += 2;
396 		}
397 
398 		/* Glide prefers to have smaller arrows relative too size
399 		* for ComboBox/ComboBoxEntry, because its cleaner,
400 		* even though it seems slightly inconsistant.
401 		*/
402 		y += 1;
403 		width -= 2;
404 		height -= 2;
405 
406 		if (button_in)
407 		{
408 			/* Arrows offset down/right on button press */
409 			x += child_offset_x;
410 			y += child_offset_y;
411 		}
412 	}
413 
414 	if (CHECK_DETAIL(detail, "menuitem"))
415 	{
416 		x -= 1;
417 	}
418 
419 	if (CHECK_DETAIL (detail, "arrow"))
420 	{
421 		x += (width%2)?0:1;
422 	}
423 
424 	/***********************************************/
425 	/* Draw Arrow                                  */
426 	/***********************************************/
427 	glide_style = GLIDE_STYLE (style);
428 
429 	canvas = ge_gdk_drawable_to_cairo (window, area);
430 
431 	if (state == GTK_STATE_INSENSITIVE)
432 	{
433 		do_glide_draw_arrow (canvas, &glide_style->color_cube.light[state], arrow_type, TRUE, x+1, y+1, width, height);
434 		do_glide_draw_arrow (canvas, &glide_style->color_cube.dark[state], arrow_type, TRUE, x, y, width, height);
435 	}
436 	else
437 	{
438 		do_glide_draw_arrow (canvas, &glide_style->color_cube.fg[state], arrow_type, TRUE, x, y, width, height);
439 	}
440 
441 	cairo_destroy(canvas);
442 }
443 
444 /***********************************************
445  * glide_draw_shadow -
446  *
447  *   Function used to draw the Shadow/Border
448  *   for most widgets/widget parts.
449  *
450  *   The Glide Shadow is primarily constructed
451  *   with an outside border of light/extra_dark
452  *   and an internal border of bg/dark.
453  ***********************************************/
454 void
glide_draw_shadow(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)455 glide_draw_shadow (GtkStyle * style,
456 	     GdkWindow * window,
457 	     GtkStateType state_type,
458 	     GtkShadowType shadow_type,
459 	     GdkRectangle * area,
460 	     GtkWidget * widget,
461 	     const gchar * detail,
462              gint x,
463              gint y,
464              gint width,
465              gint height)
466 {
467 	GlideBevelStyle bevel_style;
468 	GlideBorderType border_type;
469 
470 	cairo_t *canvas;
471  	CairoColor *background;
472 
473 	CHECK_ARGS
474 	SANITIZE_SIZE
475 
476 	/***********************************************/
477 	/* GTK Special Cases - adjust Size/Type        */
478 	/***********************************************/
479 	bevel_style = GLIDE_BEVEL_STYLE_DEFAULT;
480 	if (CHECK_DETAIL (detail, "buttondefault"))
481 	{
482 		return;
483 	}
484 
485 	if ((CHECK_DETAIL (detail, "entry")) && (widget) && (ge_is_in_combo_box (widget)))
486 	{
487 		GObject *combo_parent = G_OBJECT(ge_find_combo_box_widget_parent(widget));
488 		GtkWidget *button = g_object_get_data(combo_parent, "button");
489 
490 		if (GE_IS_WIDGET(button))
491 		{
492 			gtk_widget_queue_draw_area(button, button->allocation.x, button->allocation.y,
493 							button->allocation.width, button->allocation.height);
494 		}
495 
496 		g_object_set_data(combo_parent, "entry", widget);
497 	}
498 
499 	if (shadow_type == GTK_SHADOW_IN)
500 	{
501 		if (CHECK_DETAIL (detail, "button"))
502 		{
503 			state_type = GTK_STATE_NORMAL;
504 			bevel_style = GLIDE_BEVEL_STYLE_SMOOTH;
505 		}
506 
507 		if (((CHECK_DETAIL (detail, "entry"))
508 			|| (CHECK_DETAIL (detail, "frame")))
509 			&& widget &&
510 			((GE_IS_SPIN_BUTTON (widget))
511 				|| (ge_is_in_combo_box (widget))))
512 		{
513 			/* The Combo/ComboBoxEntry button and the SpinButton Steppers should apear
514 			* to be inset into the entry, as opposed to next to it, so we fake it
515 			* by drawing an extra 2 pixels here to ignore the right(or left)
516 			* edge, which will be drawn by the buttons.
517 			*/
518 
519 			width += 4;
520 			if ((widget) && (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL))
521 			{
522 					x -= 4;
523 			}
524 		}
525 	}
526 
527 	/***********************************************/
528 	/* Convert Shadow Type To Border Type          */
529 	/***********************************************/
530 	switch (shadow_type)
531 	{
532 		case GTK_SHADOW_ETCHED_IN:
533 			border_type = GLIDE_BORDER_TYPE_ETCHED;
534 		break;
535 
536 		case GTK_SHADOW_ETCHED_OUT:
537 			border_type = GLIDE_BORDER_TYPE_ENGRAVED;
538 		break;
539 
540 		case GTK_SHADOW_IN:
541 			border_type = GLIDE_BORDER_TYPE_IN;
542 		break;
543 
544 		case GTK_SHADOW_OUT:
545 			border_type = GLIDE_BORDER_TYPE_OUT;
546 		break;
547 
548 		default:
549 			border_type = GLIDE_BORDER_TYPE_NONE;
550 		break;
551 	}
552 
553 	/***********************************************/
554 	/* Draw Border                                 */
555 	/***********************************************/
556 	canvas = ge_gdk_drawable_to_cairo (window, area);
557  	background = &GLIDE_STYLE (style)->color_cube.bg[state_type];
558 
559 	do_glide_draw_border(canvas, background, bevel_style, border_type, x, y, width, height);
560 
561 	cairo_destroy(canvas);
562 }
563 
564 /***********************************************
565  * glide_draw_combobox_button-
566  *
567  *   Function used to draw the ComboBox button
568  *   "inset" into "entry.
569  *
570  *   Slightly Evil Hack #1
571  ***********************************************/
572 static void
glide_draw_combobox_button(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)573 glide_draw_combobox_button (GtkStyle * style,
574 		      GdkWindow * window,
575 		      GtkStateType state_type,
576 		      GtkShadowType shadow_type,
577 		      GdkRectangle * area,
578 		      GtkWidget * widget,
579 		      const gchar * detail,
580 		      gint x,
581                       gint y,
582                       gint width,
583                       gint height)
584 {
585 		GlideStyle *glide_style = GLIDE_STYLE (style);
586 
587   /* The Combo/ComboBoxEntry button should apear to be inset into the entry,
588    * as opposed to next to it, so we fake it by drawing an entry fill
589    * then an entry border - but 2 pixels bigger so it overlaps real border
590    * and so left( or right) edge doesn't actually get drawn on screen;
591    * and THEN draw the button, but essentially 4 pixels smaller.
592    */
593   GtkStyle * parent_style = style;
594   GtkStateType parent_state = state_type;
595 
596   gboolean entry_focused = FALSE;
597   gint focus_line_width = 0, focus_padding = 0, focus = 0, thick = 2;
598   gboolean interior_focus = TRUE;
599 
600   g_object_set_data(G_OBJECT(ge_find_combo_box_widget_parent(widget)), "button", widget);
601 
602   if (GTK_WIDGET_HAS_FOCUS(widget))
603   {
604 	gtk_widget_style_get (widget, "focus_line_width", &focus_line_width, NULL);
605 	gtk_widget_style_get (widget, "focus_padding", &focus_padding, NULL);
606 	gtk_widget_style_get (widget, "interior_focus", &interior_focus, NULL);
607 
608 	if (!interior_focus)
609 	{
610 		focus = -(focus_line_width);
611 		if (focus == 0)
612 		{
613 			focus = -1;
614 		}
615 		entry_focused = TRUE;
616 	}
617   }
618   else
619   {
620 		GList *child=NULL,*children = gtk_container_get_children (GTK_CONTAINER(widget->parent));
621 
622 		for (child = children; child; child = child->next)
623 		{
624 			if (GE_IS_ENTRY(child->data) && GTK_WIDGET_HAS_FOCUS(child->data))
625 			{
626 				gtk_widget_style_get (widget, "focus_line_width", &focus_line_width, NULL);
627 				gtk_widget_style_get (widget, "focus_padding", &focus_padding, NULL);
628 				gtk_widget_style_get (widget, "interior_focus", &interior_focus, NULL);
629 
630 				if (!interior_focus)
631 				{
632 					focus = focus_line_width;
633 					if (focus == 0)
634 					{
635 						focus = 1;
636 					}
637 					entry_focused = TRUE;
638 				}
639 				focus_padding = 0;
640 			}
641 		}
642 
643 		g_list_free(children);
644 	}
645 
646   if ((!(widget)) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR))
647     {
648       cairo_t *canvas;
649 
650       if (ge_is_combo_box_entry (widget)
651           || ge_is_combo_box (widget, TRUE))
652         {
653           if (!ge_is_combo_box_entry (widget))
654             {
655               if ((widget->parent))
656                 {
657                   gtk_widget_ensure_style(widget->parent);
658 
659                   parent_style = widget->parent->style;
660                   parent_state = widget->parent->state;
661                 }
662 
663 	      if (parent_state != GTK_STATE_INSENSITIVE)
664                 parent_state = GTK_STATE_NORMAL;
665 
666 /*#warning FIXME - gdk_draw_rectangle*/
667 	      gdk_draw_rectangle (window,
668 	      	                  parent_style->base_gc[parent_state],
669 			          TRUE, x - 2, y, width + 2, height);
670 
671             }
672           else
673             glide_draw_flat_box(style, window, parent_state,
674 			        GTK_SHADOW_NONE, area, widget, "entry_bg", x - 2,
675 			        y, width + 2, height);
676 
677 	      if (parent_state != GTK_STATE_INSENSITIVE)
678                 parent_state = GTK_STATE_NORMAL;
679 
680           glide_draw_shadow (style, window, parent_state, GTK_SHADOW_IN,
681   		            area, widget, "combo_box_entry", x - thick*2 - focus - focus_padding, y + focus - focus_padding,
682 				width + thick*2 + focus_padding*2, height - focus*2 + focus_padding*2);
683         }
684 #ifndef GTK_DISABLE_DEPRECATED
685       else if (ge_is_combo(widget))
686         {
687           GtkWidget *entry = widget;
688 
689 	  if (GE_IS_WIDGET(widget) && GE_IS_WIDGET(widget->parent) && GE_IS_ENTRY(GTK_COMBO (widget->parent)->entry))
690             {
691                entry = GTK_COMBO (widget->parent)->entry;
692                gtk_widget_ensure_style(entry);
693 
694                parent_style = entry->style;
695                parent_state = entry->state;
696              }
697           else if (GE_IS_WIDGET(widget->parent))
698             {
699                entry = widget->parent;
700                gtk_widget_ensure_style(entry);
701 
702                parent_style = entry->style;
703                parent_state = entry->state;
704             }
705 
706             parent_state = GTK_STATE_NORMAL;
707 
708           gtk_paint_flat_box (parent_style, window, parent_state,
709 	 		      GTK_SHADOW_NONE, area, entry, "entry_bg", x - 2,
710 			      y, width + 2, height);
711 
712           {
713             GdkRectangle shadow, clip;
714 
715             shadow.x = x - 2;
716             shadow.y = y;
717             shadow.width = width + 2;
718             shadow.height = height;
719 
720 /*		#warning FIXME - gdk_rectangle_intersect*/
721            if (area)
722               gdk_rectangle_intersect(area, &shadow, &clip);
723             else
724               clip = shadow;
725 
726             gtk_paint_shadow (parent_style, window, parent_state, GTK_SHADOW_IN,
727 	 	              &clip, entry, "combo_box_entry", x - thick*2 - focus - focus_padding, y + focus - focus_padding,
728 				width + thick*2 + focus_padding*2, height - focus*2 + focus_padding*2);
729           }
730         }
731 #else
732 #warning Disabling GtkCombo support because GTK_DISABLE_DEPRECATED is enabled.
733 #endif /* GTK_DISABLE_DEPRECATED */
734       else
735         {
736           GtkWidget *parent = widget;
737 
738           if (widget->parent)
739             parent = widget->parent;
740 
741           if ((parent))
742             {
743               gtk_widget_ensure_style(parent);
744 
745               parent_style = parent->style;
746               parent_state = parent->state;
747             }
748 
749           if (parent_state != GTK_STATE_INSENSITIVE)
750             parent_state = GTK_STATE_NORMAL;
751 
752           gtk_paint_flat_box (parent_style, window, parent_state,
753 			      GTK_SHADOW_NONE, area, parent, "entry_bg", x - 2,
754 			      y, width + 2, height);
755           gtk_paint_shadow (parent_style, window, parent_state, GTK_SHADOW_IN,
756 		   	    area, parent, "combo_box_entry", x - thick*2 - focus - focus_padding, y + focus - focus_padding,
757 				width + thick*2 + focus_padding*2, height - focus*2 + focus_padding*2);
758         }
759 
760 	canvas = ge_gdk_drawable_to_cairo (window, area);
761 
762 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_gradient[FALSE][state_type]), x + focus, y + thick + focus,
763                              width - thick - focus*2, height - thick*2 - focus*2);
764 
765         glide_draw_shadow (style, window, state_type, shadow_type, area,
766 		          widget, detail, x + focus, y + thick + focus, width - thick - focus*2, height - 2*thick - focus*2);
767 
768 #if 0
769       glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "comboarrow", GTK_ARROW_DOWN, TRUE,  x + focus + 6, y + thick + focus + 5, width - thick - focus*2 - 12, height - 2*thick - focus*2 - 10);
770 #endif
771 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,FALSE), x + focus, y + thick + focus, width - thick - focus*2, height - 2*thick - focus*2);
772 
773       cairo_destroy(canvas);
774 
775       if (entry_focused)
776       {
777              glide_draw_focus(style, window, state_type, area, widget, "combo_entry_button", x - 2, y, width + 2, height);
778       }
779     }
780   else
781     {
782       cairo_t *canvas;
783 
784       focus_padding = -focus_padding;
785 
786       if (ge_is_combo_box_entry (widget)
787           || ge_is_combo_box (widget, TRUE))
788         {
789           if (!ge_is_combo_box_entry (widget))
790             {
791               if ((widget->parent))
792                 {
793                   gtk_widget_ensure_style(widget->parent);
794 
795                   parent_style = widget->parent->style;
796                   parent_state = widget->parent->state;
797                 }
798 
799               if (parent_state != GTK_STATE_INSENSITIVE)
800                 parent_state = GTK_STATE_NORMAL;
801 
802 /*#warning FIXME - gdk_draw_rectangle*/
803 	      gdk_draw_rectangle (window, parent_style->base_gc[parent_state],
804 			          TRUE, x + focus - focus_padding, y + focus - focus_padding,
805                                         width + thick*2 - focus + focus_padding*2, height - focus*2 + focus_padding*2);
806             }
807           else
808             {
809               if (parent_state != GTK_STATE_INSENSITIVE)
810                 parent_state = GTK_STATE_NORMAL;
811 
812             glide_draw_flat_box (style, window, parent_state,
813 	  	                GTK_SHADOW_NONE, area, widget, "entry_bg",
814 				x + focus - focus_padding, y + focus - focus_padding,
815 				width + thick*2 - focus + focus_padding*2, height - focus*2 + focus_padding*2);
816 	     }
817 
818 	      if (parent_state != GTK_STATE_INSENSITIVE)
819                 parent_state = GTK_STATE_NORMAL;
820 
821           glide_draw_shadow (style, window, parent_state, GTK_SHADOW_IN,
822 	  		    area, widget, "combo_box_entry",
823                                 x + focus - focus_padding, y + focus - focus_padding,
824                                 width + thick*2 - focus + focus_padding*2, height - focus*2 + focus_padding*2);
825         }
826 #ifndef GTK_DISABLE_DEPRECATED
827       else if (ge_is_combo(widget))
828         {
829           GtkWidget *entry = widget;
830 
831 	  if (GE_IS_WIDGET(widget) && GE_IS_WIDGET(widget->parent) && GE_IS_ENTRY(GTK_COMBO (widget->parent)->entry))
832             {
833                entry = GTK_COMBO (widget->parent)->entry;
834                gtk_widget_ensure_style(entry);
835 
836                parent_style = entry->style;
837                parent_state = entry->state;
838              }
839           else if (GE_IS_WIDGET(widget->parent))
840             {
841                entry = widget->parent;
842                gtk_widget_ensure_style(entry);
843 
844                parent_style = entry->style;
845                parent_state = entry->state;
846             }
847 
848            if (parent_state != GTK_STATE_INSENSITIVE)
849              parent_state = GTK_STATE_NORMAL;
850 
851            gtk_paint_flat_box (parent_style, window, parent_state,
852 			       GTK_SHADOW_NONE, area, entry, "entry_bg",
853 				x + focus - focus_padding, y + focus - focus_padding,
854 				width + thick*2 - focus + focus_padding*2, height - focus*2 + focus_padding*2);
855            gtk_paint_shadow (parent_style, window, parent_state, GTK_SHADOW_IN,
856 			     area, entry, "combo_box_entry",
857                                 x + focus - focus_padding, y + focus - focus_padding,
858                                 width + thick*2 - focus + focus_padding*2, height - focus*2 + focus_padding*2);
859         }
860 #else
861 #warning Disabling GtkCombo support because GTK_DISABLE_DEPRECATED is enabled.
862 #endif /* GTK_DISABLE_DEPRECATED */
863       else
864         {
865           GtkWidget *parent = widget;
866 
867           if (widget->parent)
868             parent = widget->parent;
869 
870           if ((parent))
871             {
872               gtk_widget_ensure_style(parent);
873 
874               parent_style = parent->style;
875               parent_state = parent->state;
876             }
877 
878           if (parent_state != GTK_STATE_INSENSITIVE)
879             parent_state = GTK_STATE_NORMAL;
880 
881           gtk_paint_flat_box (parent_style, window, parent_state,
882 			      GTK_SHADOW_NONE, area, parent, "entry_bg",
883 				x + focus - focus_padding, y + focus - focus_padding,
884 				width + thick*2 - focus + focus_padding*2, height - focus*2 + focus_padding*2);
885           gtk_paint_shadow (parent_style, window, parent_state, GTK_SHADOW_IN,
886 		   	    area, parent, "combo_box_entry",
887                                 x + focus - focus_padding, y + focus - focus_padding,
888                                 width + thick*2 - focus + focus_padding*2, height - focus*2 + focus_padding*2);
889         }
890 
891 	canvas = ge_gdk_drawable_to_cairo (window, area);
892 
893 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_gradient[FALSE][state_type]), x + thick + focus, y + thick + focus, width - thick - focus*2, height - 2*thick - focus*2);
894 
895         glide_draw_shadow (style, window, state_type, shadow_type, area,
896 		          widget, detail, x + thick + focus, y + thick + focus, width - thick - focus*2, height - 2*thick - focus*2);
897 
898 #if 0
899       glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "comboarrow", GTK_ARROW_DOWN, TRUE,  x + thick + focus + 6, y + thick + focus + 5, width - thick - focus*2 - 12, height - 2*thick - focus*2 - 10);
900 #endif
901 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,FALSE), x + thick + focus, y + thick + focus, width - thick - focus*2, height - 2*thick - focus*2);
902 
903 	cairo_destroy(canvas);
904 
905       if (entry_focused)
906       {
907              glide_draw_focus(style, window, state_type, area, widget, "combo_entry_button", x, y, width, height);
908       }
909     }
910 }
911 
912 /***********************************************
913  * glide_draw_spinbutton_stepper-
914  *
915  *   Function used to draw the spinbutton
916  *   steppers "inset" into entry.
917  *
918  *   Slightly Evil Hack #2
919  ***********************************************/
920 static void
glide_draw_spinbutton_stepper(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)921 glide_draw_spinbutton_stepper (GtkStyle * style,
922 			 GdkWindow * window,
923 			 GtkStateType state_type,
924 			 GtkShadowType shadow_type,
925 			 GdkRectangle * area,
926 			 GtkWidget * widget,
927 			 const gchar * detail,
928 			 gint x,
929                          gint y,
930                          gint width,
931                          gint height)
932 {
933 		GlideStyle *glide_style = GLIDE_STYLE (style);
934 
935   GdkRectangle spin_area;
936 
937   /* The SpinButton Steppers should apear to be inset into the entry,
938    * as opposed to next to it, so we fake it by drawing en entry fill
939    * and then entry border - but 2 pixels bigger so it overlaps real border
940    * and so left( or right) edge doesn't actually get drawn on screen -
941    * and THEN draw the Stepper. Since we have two steppers this is slightly
942    * more complicated because we can only do half for each stepper.
943    */
944 
945   GtkStateType parent_state = widget ? GTK_WIDGET_STATE(widget) : GTK_STATE_NORMAL;
946   gboolean entry_focused = FALSE;
947   gint focus_line_width = 0, focus_padding = 0, focus = 0, thick = 2;
948   gboolean interior_focus = TRUE;
949   cairo_t *canvas;
950 
951   spin_area.x = x;
952   spin_area.y = y;
953   spin_area.width = width;
954   spin_area.height = height;
955 
956   if (widget && GTK_WIDGET_HAS_FOCUS(widget))
957   {
958 	gtk_widget_style_get (widget, "focus_line_width", &focus_line_width, NULL);
959 	gtk_widget_style_get (widget, "focus_padding", &focus_padding, NULL);
960 	gtk_widget_style_get (widget, "interior_focus", &interior_focus, NULL);
961 
962 	if (!interior_focus)
963 	{
964 		focus = focus_line_width;
965 		if (focus == 0)
966 		{
967 			focus = 1;
968 		}
969 		entry_focused = TRUE;
970 	}
971   }
972 
973   if (parent_state!= GTK_STATE_INSENSITIVE)
974   {
975 	parent_state = GTK_STATE_NORMAL;
976   }
977 
978   if ((!(widget)) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR))
979    {
980       if (CHECK_DETAIL (detail, "spinbutton_up"))
981 	{
982 	  glide_draw_flat_box (style, window, parent_state,
983 			      GTK_SHADOW_NONE, &spin_area, widget,
984 			      "entry_bg",
985 				x - thick, y + focus, width + thick - focus, height - focus*2);
986 
987 	  glide_draw_shadow (style, window, parent_state, GTK_SHADOW_IN, &spin_area, widget, detail,
988                                 x - thick, y + focus, width + thick - focus, height + thick - focus);
989 
990 	canvas = ge_gdk_drawable_to_cairo (window, area);
991 
992 	if (!((width + thick) % 2) && !focus)
993 	{
994 		x += 1;
995 		width -= 1;
996 	}
997 
998 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_gradient[FALSE][state_type]), x, y + thick + focus, width - thick - focus, height - thick - focus);
999 
1000 
1001 	  glide_draw_shadow (style, window, state_type, shadow_type, area, widget, detail,
1002                                 x, y + thick + focus, width - thick - focus, height - thick - focus);
1003 
1004 	if (!widget || (widget->requisition.height / 2) != (widget->requisition.height + 1) / 2)
1005 	{
1006 		glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "spinbutton_arrow", GTK_ARROW_UP, TRUE,
1007 					x + thick/2, y + thick + 1, width - thick*2, height - thick*2 + 1);
1008 	}
1009 	else
1010 	{
1011 		glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "spinbutton_arrow", GTK_ARROW_UP, TRUE,
1012 					x + thick/2, y + thick + 1, width - thick*2, height - thick*2);
1013 	}
1014 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,FALSE), x, y + thick + focus, width - thick - focus, height - thick - focus);
1015 
1016 	cairo_destroy(canvas);
1017 
1018           if (entry_focused)
1019             {
1020               glide_draw_focus(style, window, parent_state, area, widget, detail, x - thick, y, width + thick, height + thick);
1021             }
1022 	}
1023       else
1024 	{
1025 	  glide_draw_flat_box (style, window, parent_state,
1026 			      GTK_SHADOW_NONE, &spin_area, widget,
1027 			      "entry_bg", x - thick, y, width + thick - focus, height - focus);
1028 
1029 	  glide_draw_shadow (style, window, parent_state, GTK_SHADOW_IN, &spin_area, widget, detail,
1030 			    x - thick, y - thick, width + thick - focus, height + thick - focus);
1031 
1032 	canvas = ge_gdk_drawable_to_cairo (window, area);
1033 
1034 	if (!((width + thick) % 2) && !focus)
1035 	{
1036 		x += 1;
1037 		width -= 1;
1038 	}
1039 
1040 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_gradient[FALSE][state_type]), x, y + thick, width - thick - focus, height - thick*2 - focus);
1041 
1042 	  glide_draw_shadow (style, window, state_type, shadow_type, area, widget, detail,
1043 			    x, y , width - thick - focus, height - thick - focus);
1044 
1045 	if (!widget || (widget->requisition.height / 2) != (widget->requisition.height + 1) / 2)
1046 	{
1047 		glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "spinbutton_arrow", GTK_ARROW_DOWN, TRUE,
1048 					x + thick/2, y + thick/2 + 1 - focus, width - thick*2, height - thick*2 - 2);
1049 	}
1050 	else
1051 	{
1052 		glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "spinbutton_arrow", GTK_ARROW_DOWN, TRUE,
1053 					x + thick/2, y + thick/2 - focus, width - thick*2, height - thick*2);
1054 	}
1055 
1056 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,FALSE), x, y , width - thick - focus, height - thick - focus);
1057 	cairo_destroy(canvas);
1058 
1059           if (entry_focused)
1060             {
1061               glide_draw_focus(style, window, parent_state, area, widget, detail, x - thick, y, width + thick, height);
1062             }
1063 	}
1064     }
1065   else
1066     {
1067       if (CHECK_DETAIL (detail, "spinbutton_up"))
1068 	{
1069 	  glide_draw_flat_box (style, window, parent_state,
1070 			      GTK_SHADOW_NONE, &spin_area, widget,
1071 			      "entry_bg", x + focus, y + focus, width + thick*2 - focus, height - focus);
1072 	  glide_draw_shadow (style, window, parent_state, GTK_SHADOW_IN, &spin_area, widget, detail,
1073 				x + focus, y + focus, width + thick*2 - focus, height + thick - focus);
1074 
1075 	canvas = ge_gdk_drawable_to_cairo (window, area);
1076 
1077 	if (!((width + thick) % 2) && !focus)
1078 	{
1079 		width -= 1;
1080 	}
1081 
1082 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_gradient[FALSE][state_type]), x + thick + focus, y + thick + focus, width - thick - focus, height - thick - focus);
1083 
1084 
1085 	  glide_draw_shadow (style, window, state_type, shadow_type, area, widget, detail,
1086 				x + thick + focus, y + thick + focus , width - thick - focus, height - thick - focus);
1087 
1088 	if ((widget->requisition.height / 2) != (widget->requisition.height + 1) / 2)
1089 	{
1090 		glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "spinbutton_arrow", GTK_ARROW_UP, TRUE,
1091 					x + thick + focus, y + thick - 1 + focus, width - thick, height - thick + 1);
1092 	}
1093 	else
1094 	{
1095 		glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "spinbutton_arrow", GTK_ARROW_UP, TRUE,
1096 					x + thick + focus, y + thick, width - thick, height - thick);
1097 	}
1098 
1099 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,FALSE), x + thick + focus, y + thick + focus , width - thick - focus, height - thick - focus);
1100 	cairo_destroy(canvas);
1101           if (entry_focused)
1102             {
1103               glide_draw_focus(style, window, parent_state, area, widget, detail, x, y, width + thick*2, height + thick);
1104             }
1105 	}
1106       else
1107 	{
1108 	  glide_draw_flat_box (style, window, parent_state,
1109 			      GTK_SHADOW_NONE, &spin_area, widget,
1110 			      "entry_bg",x + focus, y, width + thick*2 - focus, height - focus);
1111 	  glide_draw_shadow (style, window, parent_state, GTK_SHADOW_IN, &spin_area, widget, detail,
1112 				x + focus , y - thick, width + thick*2 - focus, height + thick - focus);
1113 	canvas = ge_gdk_drawable_to_cairo (window, area);
1114 
1115 	if (!((width + thick) % 2) && !focus)
1116 	{
1117 		width -= 1;
1118 	}
1119 
1120 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_gradient[FALSE][state_type]), x + thick + focus, y, width - thick - focus, height - thick - focus);
1121 
1122 	  glide_draw_shadow (style, window, state_type, shadow_type, area, widget, detail,
1123                                 x + thick + focus, y, width - thick - focus, height - thick - focus);
1124 
1125 
1126 	if ((widget->requisition.height / 2) != (widget->requisition.height + 1) / 2)
1127 	{
1128 		glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "spinbutton_arrow", GTK_ARROW_DOWN, TRUE,
1129 					x + thick + focus, y + 1 - focus, width - thick, height - thick - 2);
1130 	}
1131 	else
1132 	{
1133 		glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "spinbutton_arrow", GTK_ARROW_DOWN, TRUE,
1134 					x + thick + focus, y, width - thick, height - thick);
1135 	}
1136 
1137 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,FALSE), x + thick + focus, y, width - thick - focus, height - thick - focus);
1138 
1139 	cairo_destroy(canvas);
1140 
1141 
1142           if (entry_focused)
1143             {
1144               glide_draw_focus(style, window, parent_state, area, widget, detail, x, y - thick, width + thick*2, height + thick);
1145             }
1146 	}
1147     }
1148 }
1149 
1150 /***********************************************
1151  * glide_draw_box -
1152  *
1153  *   Function used to draw the box portion of
1154  *   general widgets (buttons, entries).
1155  *
1156  *  In general this is the same as calling
1157  *  apply background and then draw shadow,
1158  *  so the bulk of this routine is actually
1159  *  to handle drawing the peculiarities of
1160  *  specific widgets which don't follow this
1161  *  in glide.
1162  ***********************************************/
1163 void
glide_draw_box(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)1164 glide_draw_box (GtkStyle * style,
1165 	  GdkWindow * window,
1166 	  GtkStateType state_type,
1167 	  GtkShadowType shadow_type,
1168 	  GdkRectangle * area,
1169 	  GtkWidget * widget,
1170 	  const gchar * detail,
1171           gint x,
1172           gint y,
1173           gint width,
1174           gint height)
1175 {
1176   GlideStyle *glide_style = GLIDE_STYLE (style);
1177   GlideBorderType border_type;
1178   cairo_t *canvas;
1179 
1180   CHECK_ARGS
1181   SANITIZE_SIZE
1182 
1183   if (GE_IS_MENU_SHELL(widget))
1184     {
1185       glide_gtk2_engine_hack_menu_shell_setup(widget);
1186     }
1187 
1188 
1189   if (CHECK_DETAIL (detail, "menuitem"))
1190     shadow_type = GTK_SHADOW_OUT;
1191 
1192 	/***********************************************/
1193 	/* Convert Shadow Type To Border Type          */
1194 	/***********************************************/
1195 	switch (shadow_type)
1196 	{
1197 		case GTK_SHADOW_ETCHED_IN:
1198 			border_type = GLIDE_BORDER_TYPE_ETCHED;
1199 		break;
1200 
1201 		case GTK_SHADOW_ETCHED_OUT:
1202 			border_type = GLIDE_BORDER_TYPE_ENGRAVED;
1203 		break;
1204 
1205 		case GTK_SHADOW_IN:
1206 			border_type = GLIDE_BORDER_TYPE_IN;
1207 		break;
1208 
1209 		case GTK_SHADOW_OUT:
1210 			border_type = GLIDE_BORDER_TYPE_OUT;
1211 		break;
1212 
1213 		default:
1214 			border_type = GLIDE_BORDER_TYPE_NONE;
1215 		break;
1216 	}
1217 
1218   canvas = ge_gdk_drawable_to_cairo (window, area);
1219 
1220   if ((CHECK_DETAIL (detail, "vscrollbar"))  || (CHECK_DETAIL (detail, "hscrollbar")))
1221     {
1222       gboolean vertical = CHECK_DETAIL (detail, "vscrollbar");
1223 
1224       ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_gradient[vertical][state_type]), x-1, y-1, width+1, height+1);
1225 
1226 	do_glide_draw_border(canvas, &glide_style->color_cube.bg[state_type],
1227 				GLIDE_BEVEL_STYLE_SMOOTHER, border_type,
1228 				x, y, width, height);
1229 
1230 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,vertical), x, y, width, height);
1231 
1232     }
1233   else if (detail && g_str_has_prefix (detail, "trough")) /* accept trough side details */
1234     {
1235 	if (GE_IS_SCALE (widget))
1236 	{
1237 		gint vborder, hborder;
1238 
1239 		/* calculate h/vborder, minimum width is 6 pixel */
1240 		if GE_IS_HSCALE (widget)
1241 		{
1242 			vborder = MIN(8, (height - 6) / 2);
1243 			hborder = 1;
1244 		}
1245 		else
1246 		{
1247 			vborder = 1;
1248 			hborder = MIN(8, (width - 6) / 2);
1249 		}
1250 
1251 		ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, GTK_STATE_NORMAL,
1252 		                      glide_style->bg_solid[GTK_STATE_NORMAL]), x, y, width, height);
1253 
1254 		ge_cairo_pattern_fill(canvas, glide_style->bg_solid[GTK_STATE_ACTIVE],
1255 		                      x+hborder, y+vborder, width-hborder*2, height-vborder*2);
1256 
1257 		if (CHECK_DETAIL (detail, "trough-lower"))
1258 			ge_cairo_pattern_fill(canvas, glide_style->bg_gradient[TRUE][GTK_STATE_SELECTED],
1259 			                      x + hborder, y+vborder, width - hborder*2, height-vborder*2);
1260 
1261 		ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, "menuitem",FALSE),
1262 				      x+hborder, y+vborder, width-hborder*2, height-vborder*2);
1263 
1264 		do_glide_draw_border(canvas, &glide_style->color_cube.bg[GTK_STATE_NORMAL],
1265 				     GLIDE_BEVEL_STYLE_SMOOTHER, GLIDE_BORDER_TYPE_IN,
1266 				     x+hborder, y+vborder, width-hborder*2, height-vborder*2);
1267 	}
1268 	else
1269 	{
1270 		ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_solid[state_type]),
1271 						x, y, width, height);
1272 
1273 		do_glide_draw_border(canvas, &glide_style->color_cube.bg[GTK_STATE_NORMAL],
1274 					GLIDE_BEVEL_STYLE_DEFAULT, GLIDE_BORDER_TYPE_IN,
1275 					x, y, width, height);
1276 	}
1277 }
1278   else if ((CHECK_DETAIL (detail, "toolbar"))
1279 	   || (CHECK_DETAIL (detail, "menubar"))
1280 	   || (GE_IS_BONOBO_TOOLBAR (widget))
1281 	   || (CHECK_DETAIL (detail, "dockitem"))
1282 	   || (CHECK_DETAIL (detail, "dockitem_bin"))
1283 	   || (CHECK_DETAIL (detail, "handlebox_bin"))
1284 	   || (CHECK_DETAIL (detail, "handlebox")))
1285     {
1286       if (((CHECK_DETAIL (detail, "dockitem_bin")) &&
1287            (GE_IS_BONOBO_DOCK_ITEM(widget))) ||
1288           ((widget) && (ge_is_bonobo_dock_item(widget->parent))))
1289 	{
1290 	  GList *children = NULL, *child = NULL;
1291 	  GtkWidget *dockitem = widget;
1292 	  gboolean has_grip = FALSE, ltr = TRUE;
1293 
1294 	  if ((!GE_IS_BONOBO_DOCK_ITEM(widget)) && (!GE_IS_BOX(widget)))
1295 	    dockitem = widget->parent;
1296 
1297 	  has_grip = GE_IS_CONTAINER(dockitem);
1298 
1299 	  ltr = (!widget) || (gtk_widget_get_direction (dockitem) == GTK_TEXT_DIR_LTR);
1300 
1301 	  if (has_grip)
1302 	  {
1303             has_grip = FALSE;
1304 
1305             children = gtk_container_get_children(GTK_CONTAINER(dockitem));
1306 
1307             for (child = g_list_first(children); child; child = g_list_next(child))
1308               {
1309 	        if (GE_IS_BONOBO_DOCK_ITEM_GRIP(child->data))
1310                   has_grip = (GTK_WIDGET_VISIBLE(child->data) &&
1311                               GTK_WIDGET_REALIZED(child->data) &&
1312                               GTK_WIDGET(child->data)->allocation.width > 1) &&
1313                               (GTK_WIDGET(child->data)->allocation.height > 1);
1314               }
1315 
1316             if (children)
1317   	      g_list_free(children);
1318           }
1319 
1320           if (has_grip)
1321             {
1322 	      /* bonobo dock items draw the handle bar grip different from
1323 	       * other toolbars - namely it draws the bin the whole size
1324 	       * and then the handle bar on top, which make the edge overlap
1325 	       * look wrong, especially relative to bonobo toolbars and
1326 	       * gtk handle bars etc. luckily the handle bar size
1327 	       * is fixed at 10, and the orientation can be grabbed
1328 	       * via gobject, so we just make sure the bin is drawn
1329 	       * NEXT to the handle bar, not beneath it
1330 	       */
1331 
1332    	      GtkOrientation tmp = GTK_ORIENTATION_HORIZONTAL;
1333 
1334 	      if GE_IS_HBOX(dockitem)
1335 	        tmp = GTK_ORIENTATION_VERTICAL;
1336 	      else if (GE_IS_BONOBO_DOCK_ITEM(dockitem))
1337 	        g_object_get (dockitem, "orientation", &tmp, NULL);
1338 
1339 	      if (tmp == GTK_ORIENTATION_HORIZONTAL)
1340 	        {
1341 	          if (dockitem == widget)
1342 	            {
1343 	              x += 8*ltr;
1344 	              width -= 8;
1345 	            }
1346 	        }
1347 	      else
1348 	        {
1349 	          if (dockitem == widget)
1350 	            {
1351 	              y += 8;
1352 	              height -= 8;
1353 	            }
1354 	        }
1355 	    }
1356 	}
1357 
1358       ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_solid[state_type]), x, y, width, height);
1359 
1360       /* If this is a menu embedded in the gnome-panel, we don't
1361        *  draw a border since it looks cleaner without one.
1362        */
1363       if ((shadow_type != GTK_SHADOW_NONE) && (widget) && (widget->parent) &&
1364 	  ((!((CHECK_DETAIL (detail, "menubar")) &&
1365 	  ge_is_panel_widget_item (widget)))))
1366         {
1367 	  cairo_save(canvas);
1368           cairo_rectangle(canvas, x, y, width, height);
1369           cairo_clip(canvas);
1370 
1371 
1372 	do_glide_draw_border(canvas, &glide_style->color_cube.bg[state_type],
1373 					GLIDE_BEVEL_STYLE_DEFAULT, GLIDE_BORDER_TYPE_OUT,
1374 					x, y,
1375 					width,
1376 					height);
1377           cairo_restore(canvas);
1378         }
1379     }
1380   else if ((CHECK_DETAIL (detail, "menuitem")))
1381     {
1382 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_gradient[FALSE][state_type]), x, y, width, height);
1383 
1384 	do_glide_draw_border(canvas, &glide_style->color_cube.bg[state_type],
1385 					GLIDE_BEVEL_STYLE_FLAT, GLIDE_BORDER_TYPE_IN,
1386 					x, y, width, height);
1387 
1388 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,FALSE), x, y, width, height);
1389     }
1390   else if ((CHECK_DETAIL (detail, "bar"))
1391 	   && (widget && GE_IS_PROGRESS_BAR (widget)))
1392     {
1393 gboolean vertical = TRUE;
1394 			switch (GTK_PROGRESS_BAR(widget)->orientation)
1395 			{
1396 				case GTK_PROGRESS_LEFT_TO_RIGHT:
1397 				case GTK_PROGRESS_RIGHT_TO_LEFT:
1398 					vertical = FALSE;
1399 				break;
1400 
1401 				case GTK_PROGRESS_BOTTOM_TO_TOP:
1402 				case GTK_PROGRESS_TOP_TO_BOTTOM:
1403 					vertical = TRUE;
1404 				break;
1405 			}
1406 
1407 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, GTK_STATE_SELECTED, glide_style->bg_gradient[!vertical][GTK_STATE_SELECTED]), x+1, y+1, width-2, height-2);
1408 	do_glide_draw_border(canvas, &glide_style->color_cube.bg[GTK_STATE_SELECTED],
1409 				GLIDE_BEVEL_STYLE_NONE, GLIDE_BORDER_TYPE_OUT,
1410 				x+1, y+1, width-2, height-2);
1411 
1412 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,vertical), x+1, y+1, width-2, height-2);
1413     }
1414   else if ((CHECK_DETAIL (detail, "button")) && widget
1415 	   && ge_is_in_combo_box (widget))
1416     {
1417       /* ComboBox Buttons are an especially complex case
1418        * so call our special function for them.
1419        */
1420       glide_draw_combobox_button (style, window, state_type, shadow_type, area,
1421 			    widget, detail, x, y, width, height);
1422     }
1423   else if ((CHECK_DETAIL (detail, "spinbutton_up"))
1424 	   || (CHECK_DETAIL (detail, "spinbutton_down")))
1425     {
1426       /* SpinButton Steppers are an especially complex case
1427        * so call our special function for them.
1428        */
1429       glide_draw_spinbutton_stepper (style, window, state_type, shadow_type, area,
1430 			       widget, detail, x, y, width, height);
1431     }
1432   else
1433     {
1434       /* default box apearance */
1435       ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_gradient[FALSE][state_type]), x, y, width, height);
1436 
1437       glide_draw_shadow (style, window, state_type, shadow_type, area,
1438 			widget, detail, x, y, width, height);
1439 
1440 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,FALSE), x, y, width, height);
1441     }
1442 
1443       /* Paint a triangle here instead of in "buttondefault"
1444          which is drawn _behind_ the current button */
1445       if ((CHECK_DETAIL (detail, "button")) && widget && GE_WIDGET_HAS_DEFAULT (widget))
1446         {
1447           cairo_save(canvas);
1448 
1449           ge_cairo_set_color(canvas, &glide_style->color_cube.bg[GTK_STATE_SELECTED]);
1450           cairo_move_to(canvas, x+2.5, y+2.5);
1451           cairo_line_to(canvas, x+11.5, y+2.5);
1452           cairo_line_to(canvas, x+2.5, y+11.5);
1453           cairo_line_to(canvas, x+2.5, y+2.5);
1454 	  cairo_fill(canvas);
1455 
1456           cairo_set_line_width (canvas, 1);
1457 
1458           ge_cairo_set_color(canvas, &glide_style->color_cube.dark[state_type]);
1459 	  cairo_move_to(canvas, x + 2.5, y + 12);
1460 	  cairo_line_to(canvas, x + 2.5, y + 2.5);
1461   	  cairo_line_to(canvas, x + 12, y + 2.5);
1462 	  cairo_stroke(canvas);
1463 
1464           ge_cairo_set_color(canvas, &glide_style->color_cube.light[state_type]);
1465           cairo_move_to(canvas, x+12, y+2.5);
1466           cairo_line_to(canvas, x+2.5, y+12);
1467 	  cairo_stroke(canvas);
1468 
1469           cairo_restore(canvas);
1470         }
1471 
1472   if (CHECK_DETAIL(detail, "optionmenu") ||  (CHECK_DETAIL(detail, "button") &&
1473        (ge_is_combo_box(widget, FALSE)) && !(ge_is_combo_box_entry(widget))))
1474     {
1475       GtkRequisition indicator_size;
1476       GtkBorder indicator_spacing;
1477       gint vline_x;
1478 
1479       if (state_type != GTK_STATE_INSENSITIVE)
1480         state_type = GTK_STATE_NORMAL;
1481 
1482       ge_option_menu_get_props (widget, &indicator_size, &indicator_spacing);
1483 
1484       if ((!widget) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL))
1485 	vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
1486       else
1487 	vline_x = x + width - (indicator_size.width + indicator_spacing.left +
1488                                indicator_spacing.right) - style->xthickness;
1489 
1490       do_glide_draw_line(canvas, &glide_style->color_cube.dark[state_type], &glide_style->color_cube.light[state_type],
1491                            area, y + style->ythickness + 1, y + height - style->ythickness - 2,
1492                            vline_x, FALSE);
1493 
1494       if ((widget) && (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL))
1495          x +=  indicator_spacing.right + style->xthickness;
1496       else
1497          x += width - indicator_size.width - indicator_spacing.right - style->xthickness;
1498 
1499       y += ((height - indicator_size.height) / 2) + 1;
1500 
1501       width = indicator_size.width;
1502       height = indicator_size.height;
1503 
1504       glide_draw_arrow (style, window, state_type, shadow_type, area, NULL, "optionmenu",
1505 	                      GTK_ARROW_DOWN, TRUE,  x,  y,  width,  height);
1506    }
1507 
1508    cairo_destroy(canvas);
1509 }
1510 
1511 /* Draw Function For Boxes Traditionally Either Without Borders,
1512 		or With A Single Pixel Line */
1513 
1514 void
glide_draw_flat_box(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)1515 glide_draw_flat_box (GtkStyle * style,
1516 	  GdkWindow * window,
1517 	  GtkStateType state_type,
1518 	  GtkShadowType shadow_type,
1519 	  GdkRectangle * area,
1520 	  GtkWidget * widget,
1521 	  const gchar * detail,
1522           gint x,
1523           gint y,
1524           gint width,
1525           gint height)
1526 {
1527 	/*#warning FIXME - FINISH draw_flat_box*/
1528 	if (CHECK_DETAIL(detail, "tooltip"))
1529 	{
1530 		GlideStyle *glide_style = GLIDE_STYLE (style);
1531 		cairo_t *canvas;
1532 
1533 		CHECK_ARGS
1534 		SANITIZE_SIZE
1535 
1536 		canvas = ge_gdk_drawable_to_cairo (window, area);
1537 
1538 		ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_solid[state_type]),
1539 						x, y, width, height);
1540 
1541 		do_glide_draw_border(canvas, &glide_style->color_cube.bg[state_type],
1542 					GLIDE_BEVEL_STYLE_FLAT, GLIDE_BORDER_TYPE_IN,
1543 					x, y, width, height);
1544 
1545 		cairo_destroy(canvas);
1546 	}
1547 	else
1548 	{
1549 		GtkStyleClass *glide_parent_class;
1550 		glide_parent_class = GTK_STYLE_CLASS (g_type_class_peek_parent (G_OBJECT_GET_CLASS(style)));
1551 		glide_parent_class->draw_flat_box (style, window, state_type, shadow_type, area,
1552 							widget, detail, x, y, width, height);
1553 	}
1554 }
1555 
1556 /***********************************************
1557  * glide_draw_tab -
1558  *
1559  *   Function pretty much only called to draw
1560  *   the arrow "tab" in the option menu
1561  ***********************************************/
1562 void
glide_draw_tab(GtkStyle * style,GdkWindow * window,GtkStateType state,GtkShadowType shadow,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)1563 glide_draw_tab (GtkStyle * style,
1564 	  GdkWindow * window,
1565 	  GtkStateType state,
1566 	  GtkShadowType shadow,
1567 	  GdkRectangle * area,
1568 	  GtkWidget * widget,
1569 	  const gchar * detail,
1570           gint x,
1571           gint y,
1572           gint width,
1573           gint height)
1574 {
1575 }
1576 
1577 /***********************************************
1578  * glide_draw_slider -
1579  *
1580  *   Function which draws scale/scrollbar slider
1581  ***********************************************/
1582 void
glide_draw_slider(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height,GtkOrientation orientation)1583 glide_draw_slider (GtkStyle * style,
1584 	     GdkWindow * window,
1585 	     GtkStateType state_type,
1586 	     GtkShadowType shadow_type,
1587 	     GdkRectangle * area,
1588 	     GtkWidget * widget,
1589 	     const gchar * detail,
1590 	     gint x,
1591 	     gint y,
1592              gint width,
1593              gint height,
1594              GtkOrientation orientation)
1595 {
1596 	GlideStyle *glide_style = GLIDE_STYLE (style);
1597 	cairo_t *canvas;
1598 
1599 	CHECK_ARGS
1600 	SANITIZE_SIZE
1601 
1602 	canvas = ge_gdk_drawable_to_cairo (window, area);
1603 
1604 	ge_cairo_pattern_fill(canvas,DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_gradient[orientation == GTK_ORIENTATION_VERTICAL][state_type]), x, y, width, height);
1605 
1606 	do_glide_draw_border(canvas, &glide_style->color_cube.bg[state_type],
1607 				(GE_IS_SCROLLBAR(widget))?GLIDE_BEVEL_STYLE_SMOOTHER:GLIDE_BEVEL_STYLE_DEFAULT, GLIDE_BORDER_TYPE_OUT,
1608 				x, y, width, height);
1609 
1610 	if (!GE_IS_SCALE(widget))
1611 	{
1612 		do_glide_draw_grip (canvas,
1613 					&glide_style->color_cube.light[state_type],
1614 					&glide_style->color_cube.dark[state_type],
1615 					x, y, width, height, orientation == GTK_ORIENTATION_VERTICAL);
1616 
1617 		ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,orientation == GTK_ORIENTATION_VERTICAL), x, y, width, height);
1618 	}
1619 	else
1620 	{
1621 		ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,orientation != GTK_ORIENTATION_VERTICAL), x, y, width, height);
1622 	}
1623 
1624 	cairo_destroy(canvas);
1625 }
1626 
1627 void
glide_draw_box_gap(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height,GtkPositionType gap_side,gint gap_pos,gint gap_size)1628 glide_draw_box_gap (GtkStyle * style,
1629                  GdkWindow * window,
1630 		 GtkStateType state_type,
1631 		 GtkShadowType shadow_type,
1632 		 GdkRectangle * area,
1633 		 GtkWidget * widget,
1634 		 const gchar * detail,
1635 		 gint x,
1636 		 gint y,
1637 		 gint width,
1638 		 gint height,
1639 		 GtkPositionType gap_side,
1640 		 gint gap_pos,
1641 		 gint gap_size)
1642 {
1643 	GlideStyle *glide_style = GLIDE_STYLE (style);
1644 	cairo_t *canvas;
1645 
1646 	CHECK_ARGS
1647 	SANITIZE_SIZE
1648 
1649 	canvas = ge_gdk_drawable_to_cairo (window, area);
1650 
1651 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, glide_style->bg_solid[state_type]), x, y, width, height);
1652 
1653 	glide_draw_shadow_gap (style, window, state_type, shadow_type, area, widget, detail,
1654 					x, y, width, height, gap_side, gap_pos, gap_size);
1655 
1656 	cairo_destroy(canvas);
1657 }
1658 
1659 void
glide_draw_shadow_gap(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height,GtkPositionType gap_side,gint gap_pos,gint gap_size)1660 glide_draw_shadow_gap (GtkStyle * style,
1661                  GdkWindow * window,
1662 		 GtkStateType state_type,
1663 		 GtkShadowType shadow_type,
1664 		 GdkRectangle * area,
1665 		 GtkWidget * widget,
1666 		 const gchar * detail,
1667 		 gint x,
1668 		 gint y,
1669 		 gint width,
1670 		 gint height,
1671 		 GtkPositionType gap_side,
1672 		 gint gap_pos,
1673 		 gint gap_size)
1674 {
1675 	GlideSide side;
1676 	GlideBorderType border_type;
1677 	GlideBevelStyle bevel_style;
1678 	cairo_t *canvas;
1679 
1680 
1681 	/***********************************************/
1682 	/* GTK Sanity Checks                           */
1683 	/***********************************************/
1684 	CHECK_ARGS
1685 	SANITIZE_SIZE
1686 
1687 	if (shadow_type == GTK_SHADOW_NONE)
1688 		return;
1689 
1690 	/***********************************************/
1691 	/* GTK Special Cases - adjust Size/Offset      */
1692 	/***********************************************/
1693 	side = GLIDE_SIDE_NONE;
1694 
1695 	if (gap_size > 0)
1696 	{
1697 		switch (gap_side)
1698 		{
1699 			case GTK_POS_BOTTOM:
1700 				side = GLIDE_SIDE_BOTTOM;
1701 			break;
1702 
1703 			case GTK_POS_TOP:
1704 				side = GLIDE_SIDE_TOP;
1705 			break;
1706 
1707 			case GTK_POS_RIGHT:
1708 				side = GLIDE_SIDE_RIGHT;
1709 			break;
1710 
1711 			case GTK_POS_LEFT:
1712 				side = GLIDE_SIDE_LEFT;
1713 			break;
1714 
1715 			default:
1716 			break;
1717 		}
1718 
1719 		switch (side)
1720 		{
1721 			case GLIDE_SIDE_BOTTOM:
1722 				if (((gap_pos + gap_size) != width) && ((gap_pos) != 0))
1723 				{
1724 					gap_pos -= 1;
1725 					gap_size += 1;
1726 				}
1727 			case GLIDE_SIDE_TOP:
1728 				if ((gap_pos + gap_size) == width)
1729 				{
1730 					gap_pos -= 1;
1731 				}
1732 
1733 				gap_size += 1;
1734 			break;
1735 
1736 			case GLIDE_SIDE_RIGHT:
1737 				if (((gap_pos + gap_size) != height) && ((gap_pos) != 0))
1738 				{
1739 					gap_pos -= 1;
1740 					gap_size += 1;
1741 				}
1742 			case GLIDE_SIDE_LEFT:
1743 				if ((gap_pos + gap_size) == height)
1744 				{
1745 					gap_pos -= 1;
1746 				}
1747 
1748 				gap_size += 1;
1749 			break;
1750 
1751 			default:
1752 			break;
1753 		}
1754 
1755 		gap_pos += 1;
1756 		gap_size -= 2;
1757 	}
1758 
1759 
1760 	/***********************************************/
1761 	/* Convert Shadow Type To Border Type          */
1762 	/***********************************************/
1763 	switch (shadow_type)
1764 	{
1765 		case GTK_SHADOW_ETCHED_IN:
1766 			border_type = GLIDE_BORDER_TYPE_ETCHED;
1767 		break;
1768 
1769 		case GTK_SHADOW_ETCHED_OUT:
1770 			border_type = GLIDE_BORDER_TYPE_ENGRAVED;
1771 		break;
1772 
1773 		case GTK_SHADOW_IN:
1774 			border_type = GLIDE_BORDER_TYPE_IN;
1775 		break;
1776 
1777 		case GTK_SHADOW_OUT:
1778 			border_type = GLIDE_BORDER_TYPE_OUT;
1779 		break;
1780 
1781 		default:
1782 			border_type = GLIDE_BORDER_TYPE_NONE;
1783 		break;
1784 	}
1785 
1786 
1787 	/***********************************************/
1788 	/* Draw Border                                 */
1789 	/***********************************************/
1790 	bevel_style = GLIDE_BEVEL_STYLE_DEFAULT;
1791 
1792 	canvas = ge_gdk_drawable_to_cairo (window, area);
1793 
1794 	do_glide_draw_border_with_gap(canvas,
1795 					&GLIDE_STYLE(style)->color_cube.bg[state_type],
1796 					bevel_style, border_type,
1797 					x, y, width, height,
1798 					side, gap_pos, gap_size);
1799 
1800 	cairo_destroy(canvas);
1801 }
1802 
1803 /***********************************************
1804  * glide_draw_extension -
1805  *
1806  *   Function which draws notebook extensions -
1807  *   aka, tabs.
1808  *
1809  *  This routine is so complex mostly because
1810  *  it tries to draw a faked 1-2 pixel rounded
1811  *  corner.
1812  ***********************************************/
1813 void
glide_draw_extension(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height,GtkPositionType gap_side)1814 glide_draw_extension (GtkStyle * style,
1815 		GdkWindow * window,
1816 		GtkStateType state_type,
1817 		GtkShadowType shadow_type,
1818 		GdkRectangle * area,
1819 		GtkWidget * widget,
1820 		const gchar * detail,
1821 		gint x,
1822 		gint y,
1823                 gint width,
1824                 gint height,
1825                 GtkPositionType gap_side)
1826 {
1827 	GlideStyle *glide_style = GLIDE_STYLE (style);
1828 
1829 	gint widget_x = 0, widget_y = 0, widget_width = 0, widget_height = 0;
1830 
1831 	GdkRectangle clip, shadow;
1832 	CairoPattern *pattern;
1833 
1834 	gint gap_pos = 0, gap_shrink = 0;
1835 
1836 	GlideSide side;
1837 	GlideBorderType border_type;
1838 	GlideBevelStyle bevel_style;
1839 	cairo_t *canvas;
1840 
1841 	CHECK_ARGS
1842 	SANITIZE_SIZE
1843 
1844 	shadow.x = x;
1845 	shadow.y = y;
1846 	shadow.width = width;
1847 	shadow.height = height;
1848  	clip = shadow;
1849 
1850 	/* GTK doesn't overlap Extensions and Notebooks,
1851 		but rather a tab is drawn with a "gap" side.
1852 
1853 		Instead of long draw cases per gap side,
1854 		call standard draw, but clipped to size,
1855 		and overdraw edge thickness + one on gap side.
1856 
1857 		To fake the apearance of overlap on edge aligned tabs
1858 		increase clip by one on gap side. */
1859 
1860 	if (widget && (GE_IS_NOTEBOOK (widget)))
1861 	{
1862 		widget_x = (widget->allocation.x + GTK_CONTAINER (widget)->border_width);
1863 		widget_y = (widget->allocation.y + GTK_CONTAINER (widget)->border_width);
1864 		widget_width = (widget->allocation.width - 2*GTK_CONTAINER (widget)->border_width);
1865 		widget_height = (widget->allocation.height - 2*GTK_CONTAINER (widget)->border_width);
1866 	}
1867 
1868 	pattern = glide_style->bg_solid[state_type];
1869 
1870 	if ((widget && GE_IS_NOTEBOOK (widget)) && (state_type==GTK_STATE_NORMAL))
1871 	{
1872 		pattern = glide_style->active_tab_gradient[gap_side][state_type];
1873 		gap_pos = 1;
1874 		gap_shrink = 2;
1875 	}
1876 
1877 	switch (gap_side)
1878 	{
1879 		case GTK_POS_TOP:
1880 			if (GTK_CHECK_VERSION(2,10,0) ||
1881 				((widget && GE_IS_NOTEBOOK (widget)) &&
1882 				((x==widget_x) ||
1883 				((x + width) == (widget_x + widget_width)))))
1884 			{
1885 				clip.y -= 1;
1886 				clip.height += 2;
1887 
1888 				if (!GTK_CHECK_VERSION(2,10,0))
1889 				{
1890 					height -= 1;
1891 				}
1892 			}
1893 
1894 			y -= 3;
1895 			height += 3;
1896 		break;
1897 
1898 		case GTK_POS_LEFT:
1899 			if (GTK_CHECK_VERSION(2,10,0) ||
1900 				((widget && GE_IS_NOTEBOOK (widget)) &&
1901 				((y==widget_y) ||
1902 				((y + height) == (widget_y + widget_height)))))
1903 			{
1904 				clip.x -= 1;
1905 				clip.width += 2;
1906 
1907 				if (!GTK_CHECK_VERSION(2,10,0))
1908 				{
1909 					x -= 1;
1910 				}
1911 			}
1912 
1913 			x -= 3;
1914 			width += 3;
1915 		break;
1916 
1917 		default:
1918 		case GTK_POS_BOTTOM:
1919 			if (GTK_CHECK_VERSION(2,10,0) ||
1920 				((widget && GE_IS_NOTEBOOK (widget)) &&
1921 				((x==widget_x) ||
1922 				((x + width) == (widget_x + widget_width)))))
1923 			{
1924 				clip.height += 1;
1925 				gap_shrink-=2;
1926 			}
1927 
1928 			height += 3;
1929 		break;
1930 
1931 		case GTK_POS_RIGHT:
1932 			if (GTK_CHECK_VERSION(2,10,0) ||
1933 				((widget && GE_IS_NOTEBOOK (widget)) &&
1934 				((y==widget_y) ||
1935 				((y + height) == (widget_y + widget_height)))))
1936 			{
1937 				clip.width += 1;
1938 				gap_shrink-=2;
1939 			}
1940 			width += 3;
1941 		break;
1942 	}
1943 
1944 	/***********************************************/
1945 	/* GTK Special Cases - adjust Size/Offset      */
1946 	/***********************************************/
1947 	side = GLIDE_SIDE_NONE;
1948 
1949 	switch (gap_side)
1950 	{
1951 		case GTK_POS_BOTTOM:
1952 			side = GLIDE_SIDE_BOTTOM;
1953 		break;
1954 
1955 		case GTK_POS_TOP:
1956 			side = GLIDE_SIDE_TOP;
1957 		break;
1958 
1959 		case GTK_POS_RIGHT:
1960 			side = GLIDE_SIDE_RIGHT;
1961 		break;
1962 
1963 		case GTK_POS_LEFT:
1964 			side = GLIDE_SIDE_LEFT;
1965 		break;
1966 
1967 		default:
1968 		break;
1969 	}
1970 
1971 	/***********************************************/
1972 	/* Convert Shadow Type To Border Type          */
1973 	/***********************************************/
1974 	switch (shadow_type)
1975 	{
1976 		case GTK_SHADOW_ETCHED_IN:
1977 			border_type = GLIDE_BORDER_TYPE_ETCHED;
1978 		break;
1979 
1980 		case GTK_SHADOW_ETCHED_OUT:
1981 			border_type = GLIDE_BORDER_TYPE_ENGRAVED;
1982 		break;
1983 
1984 		case GTK_SHADOW_IN:
1985 			border_type = GLIDE_BORDER_TYPE_IN;
1986 		break;
1987 
1988 		case GTK_SHADOW_OUT:
1989 			border_type = GLIDE_BORDER_TYPE_OUT;
1990 		break;
1991 
1992 		default:
1993 			border_type = GLIDE_BORDER_TYPE_NONE;
1994 		break;
1995 	}
1996 
1997 
1998 	/***********************************************/
1999 	/* Draw Border                                 */
2000 	/***********************************************/
2001 	bevel_style = GLIDE_BEVEL_STYLE_DEFAULT;
2002 	canvas = ge_gdk_drawable_to_cairo (window, area);
2003 
2004 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, pattern), shadow.x, shadow.y, shadow.width, shadow.height);
2005 
2006 	cairo_rectangle(canvas, clip.x, clip.y, clip.width, clip.height);
2007 	cairo_clip(canvas);
2008 
2009 	do_glide_draw_border_with_gap(canvas,
2010 					&GLIDE_STYLE(style)->color_cube.bg[state_type],
2011 					bevel_style, border_type,
2012 					x, y, width, height, side,
2013 					gap_pos, (((side==GLIDE_SIDE_TOP) || (side==GLIDE_SIDE_BOTTOM))?width:height)-gap_shrink);
2014 
2015 	cairo_destroy(canvas);
2016 
2017 }
2018 
2019 /***********************************************
2020  * glide_draw_handle -
2021  *
2022  *   Function which draws Handle box-
2023  *   aka toolbar drag grip/paned drag grip
2024  ***********************************************/
2025 void
glide_draw_handle(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GtkShadowType shadow_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height,GtkOrientation orientation)2026 glide_draw_handle (GtkStyle * style,
2027 	     GdkWindow * window,
2028 	     GtkStateType state_type,
2029 	     GtkShadowType shadow_type,
2030 	     GdkRectangle * area,
2031 	     GtkWidget * widget,
2032 	     const gchar * detail,
2033 	     gint x,
2034 	     gint y,
2035              gint width,
2036              gint height,
2037              GtkOrientation orientation)
2038 {
2039   GlideStyle *glide_style = GLIDE_STYLE (style);
2040   cairo_t *canvas;
2041 
2042   CHECK_ARGS
2043   SANITIZE_SIZE
2044 
2045   if (GE_IS_BONOBO_DOCK_ITEM_GRIP(widget) &&
2046      (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) &&
2047       orientation == (GTK_ORIENTATION_HORIZONTAL))
2048   {
2049     x = widget->parent->allocation.width - widget->allocation.width;
2050     y = widget->parent->allocation.height - widget->allocation.height;
2051     width = widget->allocation.width;
2052     height = widget->allocation.height;
2053 
2054     area = NULL;
2055   }
2056 
2057       canvas = ge_gdk_drawable_to_cairo (window, area);
2058 
2059       if (GE_IS_HANDLE_BOX (widget))
2060 	{
2061 	  /* handle box apears to be broken in that
2062 	   * it doesn't pass the orientation properly,
2063 	   * but always passes as vertical, so we look
2064 	   * it up ourselves.
2065 	   */
2066 	  switch (gtk_handle_box_get_handle_position
2067 		  (GTK_HANDLE_BOX (widget)))
2068 	    {
2069 	    case GTK_POS_LEFT:
2070 	    case GTK_POS_RIGHT:
2071 	      orientation = GTK_ORIENTATION_VERTICAL;
2072 	      break;
2073 
2074 	    case GTK_POS_TOP:
2075 	    case GTK_POS_BOTTOM:
2076 	      orientation = GTK_ORIENTATION_HORIZONTAL;
2077 	      break;
2078 	    }
2079 	}
2080       else
2081 	{
2082 	  if ((CHECK_DETAIL (detail, "handlebox")
2083 	       && (!GE_IS_HANDLE_BOX_ITEM (widget))))
2084 	    {
2085 	      /* panel_applet_frame used by the panel is broken,
2086 	       * always passes orientation == horizontal
2087 	       * since we don't know anything about the panel
2088 	       * here, we just determine orientation by size.
2089 	       *
2090 	       * If this is on a PanelWidget, we also offset the
2091 	       * actual drag bar by 2 pixels, since we draw
2092 	       * a line next to it instead of drawing a border
2093 	       * around it.
2094 	       */
2095 	      if (width < height)
2096 		{
2097 		  orientation = GTK_ORIENTATION_HORIZONTAL;
2098 		  if (ge_is_panel_widget_item (widget))
2099 		    x += 2;
2100 		}
2101 	      else
2102 		{
2103 		  orientation = GTK_ORIENTATION_VERTICAL;
2104 		  if (ge_is_panel_widget_item (widget))
2105 		    y += 2;
2106 		}
2107 	    }
2108 	}
2109 
2110 	ge_cairo_pattern_fill(canvas, DEFAULT_BACKGROUND_PATTERN(glide_style, state_type, (GE_IS_PANED(widget))?glide_style->bg_solid[state_type]:
2111 				glide_style->bg_gradient[orientation == (GTK_ORIENTATION_VERTICAL)][state_type]), x, y, width, height);
2112 
2113       if (ge_is_panel_widget_item (widget)
2114 	  && (CHECK_DETAIL (detail, "handlebox")
2115 	      && (!GE_IS_HANDLE_BOX_ITEM (widget)))
2116 	  && (!(GE_IS_HANDLE_BOX (widget))))
2117 	{
2118 		/* draw the drag bar */
2119 		if (orientation == GTK_ORIENTATION_VERTICAL)
2120 		{
2121 			ge_cairo_simple_border (canvas, &glide_style->color_cube.light[state_type],
2122 							&glide_style->color_cube.dark[state_type],
2123 							x + style->xthickness + 1, y + height / 2 - 1,
2124 							width - style->xthickness - 3, 3, FALSE);
2125 		}
2126 		else
2127 		{
2128 			ge_cairo_simple_border (canvas, &glide_style->color_cube.light[state_type],
2129 							&glide_style->color_cube.dark[state_type], x + width / 2 - 1,
2130 							y + style->ythickness + 1, 3,
2131 							height - style->ythickness - 3, FALSE);
2132 		}
2133 
2134 		/* If this is on a PanelWidget, we draw a line
2135 		* next to it instead of drawing a border around it.
2136 		*/
2137 		if (orientation == GTK_ORIENTATION_VERTICAL)
2138 		{
2139 			ge_cairo_line (canvas, &glide_style->color_cube.dark[state_type], x + 1, y + 0,
2140 					x + width - 2, y + 0);
2141 			ge_cairo_line (canvas, &glide_style->color_cube.light[state_type], x + 1,
2142 					y + 1, x + width - 2, y + 1);
2143 		}
2144 		else
2145 		{
2146 			ge_cairo_line (canvas, &glide_style->color_cube.dark[state_type], x + 0, y + 1,
2147 					x + 0, y + height - 2);
2148 			ge_cairo_line (canvas, &glide_style->color_cube.light[state_type], x + 1,
2149 					y + 1, x + 1, y + height - 2);
2150 		}
2151 	}
2152       else
2153 	{
2154 	  gboolean skip_shadow = FALSE;
2155 
2156 	do_glide_draw_grip (canvas,
2157 			&glide_style->color_cube.light[GTK_STATE_NORMAL],
2158 			&glide_style->color_cube.dark[GTK_STATE_NORMAL],
2159 			x, y, width, height, orientation == GTK_ORIENTATION_VERTICAL);
2160 
2161           if (GE_IS_BONOBO_DOCK_ITEM_GRIP(widget))
2162             {
2163               if GE_IS_BOX(widget->parent)
2164                 {
2165                   GList *children = NULL, *child = NULL;
2166 
2167                   children = gtk_container_get_children(GTK_CONTAINER(widget->parent));
2168 
2169                   for (child = g_list_first(children); child; child = g_list_next(child))
2170                     {
2171 	              if (GE_IS_BOX(child->data))
2172 	                {
2173 	                  skip_shadow = TRUE;
2174 	                  child = NULL;
2175 	                }
2176                     }
2177 
2178                   if (children)
2179   	            g_list_free(children);
2180                 }
2181             }
2182           else
2183 		skip_shadow = GE_IS_PANED(widget);
2184 
2185           if (!skip_shadow)
2186             {
2187 		do_glide_draw_border(canvas, &glide_style->color_cube.bg[state_type],
2188 				GLIDE_BEVEL_STYLE_DEFAULT, GLIDE_BORDER_TYPE_OUT,
2189 				x, y, width, height);
2190             }
2191 	ge_cairo_pattern_fill(canvas, DEFAULT_OVERLAY_PATTERN(glide_style, detail,orientation == GTK_ORIENTATION_VERTICAL), x, y, width, height);
2192 	}
2193 
2194 	cairo_destroy(canvas);
2195 }
2196 
2197 void
glide_draw_focus(GtkStyle * style,GdkWindow * window,GtkStateType state_type,GdkRectangle * area,GtkWidget * widget,const gchar * detail,gint x,gint y,gint width,gint height)2198 glide_draw_focus(GtkStyle *style,
2199            GdkWindow *window,
2200            GtkStateType state_type,
2201            GdkRectangle *area,
2202            GtkWidget *widget,
2203            const gchar *detail,
2204            gint x,
2205            gint y,
2206            gint width,
2207            gint height)
2208 {
2209 	GlideStyle *glide_style = GLIDE_STYLE (style);
2210 
2211 	gboolean interior_focus = FALSE;
2212 	gint line_width = 1;
2213 
2214 	CHECK_ARGS
2215 
2216 	/* Fallback on GTK's Line Pattern */
2217 	if (widget)
2218 	{
2219 		gtk_widget_style_get (widget, "focus-line-width", &line_width, NULL);
2220 
2221 		gtk_widget_style_get (widget, "interior_focus", &interior_focus, NULL);
2222 	}
2223 
2224 
2225 	if (interior_focus)
2226 	{
2227 		GtkStyleClass *glide_parent_class;
2228 		glide_parent_class = GTK_STYLE_CLASS (g_type_class_peek_parent (G_OBJECT_GET_CLASS(style)));
2229 		glide_parent_class->draw_focus(style, window, state_type, area, widget, detail, x, y, width, height);
2230 	}
2231 	else
2232 	{
2233 		cairo_t *canvas = ge_gdk_drawable_to_cairo (window, area);
2234 
2235 		ge_cairo_set_color(canvas, &glide_style->color_cube.bg[GTK_STATE_SELECTED]);
2236 		cairo_set_line_width(canvas, line_width);
2237 
2238 	 	if (CHECK_DETAIL(detail, "button") && (ge_is_in_combo_box (widget)))
2239 		{
2240 			gint thick = 2;
2241 			GtkWidget *entry;
2242 
2243 			if ((!widget) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR))
2244 			{
2245 				ge_cairo_stroke_rectangle(canvas, x - thick + line_width*2, y + thick, width - line_width*2, height - thick*2);
2246 			}
2247 			else
2248 			{
2249 				ge_cairo_stroke_rectangle(canvas, x + thick, y + thick, width - line_width*2, height - thick*2);
2250 			}
2251 
2252 			entry = g_object_get_data(G_OBJECT(ge_find_combo_box_widget_parent (widget)), "entry");
2253 		}
2254 	 	else if (CHECK_DETAIL(detail, "entry") && (GE_IS_SPIN_BUTTON(widget)) )
2255 		{
2256 			if ((!widget) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR))
2257 			{
2258 				ge_cairo_stroke_rectangle(canvas, x + 0.5, y + 0.5, width + line_width - 1, height - 1);
2259 			}
2260 			else
2261 			{
2262 				ge_cairo_stroke_rectangle(canvas, x - line_width + 0.5, y + 0.5, width + line_width - 1, height - 1);
2263 			}
2264 		}
2265  		else if (CHECK_DETAIL(detail, "entry") && (ge_is_in_combo_box (widget)))
2266 		{
2267 			GtkWidget *button = g_object_get_data(G_OBJECT(ge_find_combo_box_widget_parent (widget)), "button");
2268 
2269 			if (GE_IS_WIDGET(button))
2270 			{
2271 				gtk_widget_queue_draw_area(button, button->allocation.x, button->allocation.y,
2272 								button->allocation.width, button->allocation.height);
2273 			}
2274 
2275 			if ((!widget) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR))
2276 			{
2277 				ge_cairo_stroke_rectangle(canvas, x + 0.5, y + 0.5, width + line_width - 1, height - 1);
2278 			}
2279 			else
2280 			{
2281 				ge_cairo_stroke_rectangle(canvas, x - line_width + 0.5, y + 0.5, width + line_width - 1, height - 1);
2282 			}
2283 		}
2284 		else if (CHECK_DETAIL(detail, "spinbutton_up"))
2285 		{
2286 			if ((!widget) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR))
2287 			{
2288 				cairo_rectangle(canvas, x + line_width, y, width - line_width, height);
2289 			}
2290 			else
2291 			{
2292 				cairo_rectangle(canvas, x, y, width - line_width, height);
2293 			}
2294 
2295 			cairo_clip(canvas);
2296 			ge_cairo_stroke_rectangle(canvas, x + 0.5, y + 0.5, width - 1, height + line_width - 1);
2297 		}
2298 	        else if (CHECK_DETAIL(detail, "spinbutton_down"))
2299 		{
2300 			if ((!widget) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR))
2301 			{
2302 				cairo_rectangle(canvas, x + line_width, y, width - line_width, height);
2303 			}
2304 			else
2305 			{
2306 				cairo_rectangle(canvas, x, y, width - line_width, height);
2307 			}
2308 
2309 			cairo_clip(canvas);
2310 			ge_cairo_stroke_rectangle(canvas, x + 0.5, y - line_width  + 0.5, width - 1, height + line_width - 1);
2311 		}
2312 	        else if (CHECK_DETAIL(detail, "combo_entry_button"))
2313 		{
2314 			if ((!widget) || (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR))
2315 			{
2316 				cairo_rectangle(canvas, x + line_width, y, width - line_width, height + 1);
2317 				cairo_clip(canvas);
2318 
2319 				ge_cairo_stroke_rectangle(canvas, x + 0.5, y + 0.5, width - 1, height - 1);
2320 			}
2321 			else
2322 			{
2323 				cairo_rectangle(canvas, x, y, width, height + 1);
2324 				cairo_clip(canvas);
2325 
2326 				ge_cairo_stroke_rectangle(canvas, x+0.5, y+0.5, width + line_width - 1, height - 1);
2327 			}
2328 		}
2329 		else
2330 		{
2331   			ge_cairo_stroke_rectangle(canvas, x+0.5, y+0.5, width-1, height-1);
2332 		}
2333 
2334 		cairo_destroy(canvas);
2335 	}
2336 }
2337 
2338 void
glide_draw_layout(GtkStyle * style,GdkWindow * window,GtkStateType state_type,gboolean use_text,GdkRectangle * area,GtkWidget * widget,const char * detail,int x,int y,PangoLayout * layout)2339 glide_draw_layout (GtkStyle        *style,
2340 	     GdkWindow       *window,
2341 	     GtkStateType     state_type,
2342 	     gboolean         use_text,
2343 	     GdkRectangle    *area,
2344 	     GtkWidget       *widget,
2345 	     const char      *detail,
2346 	     int              x,
2347 	     int              y,
2348 	     PangoLayout      *layout)
2349 {
2350 	GdkGC *gc;
2351 
2352 	CHECK_ARGS
2353 	use_text &= !ge_is_combo_box(widget, FALSE);
2354 
2355 /*	#warning FIXME - gdk gdk gdk*/
2356 
2357 	gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
2358 
2359 	if (area)
2360 	{
2361 		gdk_gc_set_clip_rectangle (gc, area);
2362 	}
2363 
2364 	if ((state_type==GTK_STATE_INSENSITIVE) && !use_text)
2365 	{
2366 		gdk_draw_layout_with_colors(window, gc, x+1, y+1, layout, &style->light[state_type], NULL);
2367 		gdk_draw_layout_with_colors(window, gc, x, y, layout, &style->dark[state_type], NULL);
2368 	}
2369 	else
2370 	{
2371 		gdk_draw_layout (window, gc, x, y, layout);
2372 	}
2373 
2374 	if (area)
2375 	{
2376 		gdk_gc_set_clip_rectangle (gc, NULL);
2377 	}
2378 }
2379