2002-02-06 22:07:56 -05:00
/* Metacity theme parsing */
/*
* Copyright ( C ) 2001 Havoc Pennington
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation ; either version 2 of the
* License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA
* 02111 - 1307 , USA .
*/
# include <config.h>
# include "theme-parser.h"
# include "util.h"
# include <string.h>
# include <stdlib.h>
typedef enum
{
STATE_START ,
STATE_THEME ,
/* info section */
STATE_INFO ,
STATE_NAME ,
STATE_AUTHOR ,
STATE_COPYRIGHT ,
STATE_DATE ,
STATE_DESCRIPTION ,
/* constants */
STATE_CONSTANT ,
/* geometry */
STATE_FRAME_GEOMETRY ,
STATE_DISTANCE ,
STATE_BORDER ,
2002-06-03 22:13:00 -04:00
STATE_ASPECT_RATIO ,
2002-02-06 22:07:56 -05:00
/* draw ops */
STATE_DRAW_OPS ,
STATE_LINE ,
STATE_RECTANGLE ,
STATE_ARC ,
STATE_CLIP ,
STATE_TINT ,
STATE_GRADIENT ,
STATE_IMAGE ,
STATE_GTK_ARROW ,
STATE_GTK_BOX ,
STATE_GTK_VLINE ,
STATE_ICON ,
STATE_TITLE ,
STATE_INCLUDE , /* include another draw op list */
2002-02-09 20:10:33 -05:00
STATE_TILE , /* tile another draw op list */
2002-02-06 22:07:56 -05:00
/* sub-parts of gradient */
STATE_COLOR ,
/* frame style */
STATE_FRAME_STYLE ,
STATE_PIECE ,
STATE_BUTTON ,
/* style set */
STATE_FRAME_STYLE_SET ,
STATE_FRAME ,
/* assigning style sets to windows */
STATE_WINDOW ,
/* and menu icons */
STATE_MENU_ICON
} ParseState ;
typedef struct
{
GSList * states ;
const char * theme_name ; /* name of theme (directory it's in) */
char * theme_file ; /* theme filename */
char * theme_dir ; /* dir the theme is inside */
MetaTheme * theme ; /* theme being parsed */
char * name ; /* name of named thing being parsed */
MetaFrameLayout * layout ; /* layout being parsed if any */
MetaDrawOpList * op_list ; /* op list being parsed if any */
MetaDrawOp * op ; /* op being parsed if any */
MetaFrameStyle * style ; /* frame style being parsed if any */
MetaFrameStyleSet * style_set ; /* frame style set being parsed if any */
MetaFramePiece piece ; /* position of piece being parsed */
MetaButtonType button_type ; /* type of button/menuitem being parsed */
MetaButtonState button_state ; /* state of button being parsed */
MetaMenuIconType menu_icon_type ; /* type of menu icon being parsed */
GtkStateType menu_icon_state ; /* state of menu icon being parsed */
} ParseInfo ;
static void set_error ( GError * * err ,
GMarkupParseContext * context ,
int error_domain ,
int error_code ,
const char * format ,
. . . ) G_GNUC_PRINTF ( 5 , 6 ) ;
static void add_context_to_error ( GError * * err ,
GMarkupParseContext * context ) ;
static void parse_info_init ( ParseInfo * info ) ;
static void parse_info_free ( ParseInfo * info ) ;
static void push_state ( ParseInfo * info ,
ParseState state ) ;
static void pop_state ( ParseInfo * info ) ;
static ParseState peek_state ( ParseInfo * info ) ;
static void parse_toplevel_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error ) ;
static void parse_info_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error ) ;
static void parse_geometry_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error ) ;
static void parse_draw_op_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error ) ;
static void parse_gradient_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error ) ;
static void parse_style_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error ) ;
static void parse_style_set_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error ) ;
static void parse_piece_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error ) ;
static void parse_button_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error ) ;
static void parse_menu_icon_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error ) ;
static void start_element_handler ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
gpointer user_data ,
GError * * error ) ;
static void end_element_handler ( GMarkupParseContext * context ,
const gchar * element_name ,
gpointer user_data ,
GError * * error ) ;
static void text_handler ( GMarkupParseContext * context ,
const gchar * text ,
gsize text_len ,
gpointer user_data ,
GError * * error ) ;
static GMarkupParser metacity_theme_parser = {
start_element_handler ,
end_element_handler ,
text_handler ,
NULL ,
NULL
} ;
static void
set_error ( GError * * err ,
GMarkupParseContext * context ,
int error_domain ,
int error_code ,
const char * format ,
. . . )
{
int line , ch ;
va_list args ;
char * str ;
g_markup_parse_context_get_position ( context , & line , & ch ) ;
va_start ( args , format ) ;
str = g_strdup_vprintf ( format , args ) ;
va_end ( args ) ;
g_set_error ( err , error_domain , error_code ,
_ ( " Line %d character %d: %s " ) ,
line , ch , str ) ;
g_free ( str ) ;
}
static void
add_context_to_error ( GError * * err ,
GMarkupParseContext * context )
{
int line , ch ;
char * str ;
if ( err = = NULL | | * err = = NULL )
return ;
g_markup_parse_context_get_position ( context , & line , & ch ) ;
str = g_strdup_printf ( _ ( " Line %d character %d: %s " ) ,
line , ch , ( * err ) - > message ) ;
g_free ( ( * err ) - > message ) ;
( * err ) - > message = str ;
}
static void
parse_info_init ( ParseInfo * info )
{
info - > theme_file = NULL ;
info - > states = g_slist_prepend ( NULL , GINT_TO_POINTER ( STATE_START ) ) ;
info - > theme = NULL ;
info - > name = NULL ;
info - > layout = NULL ;
info - > op_list = NULL ;
info - > op = NULL ;
info - > style = NULL ;
info - > style_set = NULL ;
info - > piece = META_FRAME_PIECE_LAST ;
info - > button_type = META_BUTTON_TYPE_LAST ;
info - > button_state = META_BUTTON_STATE_LAST ;
}
static void
parse_info_free ( ParseInfo * info )
{
g_free ( info - > theme_file ) ;
g_free ( info - > theme_dir ) ;
g_slist_free ( info - > states ) ;
if ( info - > theme )
meta_theme_free ( info - > theme ) ;
if ( info - > layout )
meta_frame_layout_unref ( info - > layout ) ;
if ( info - > op_list )
meta_draw_op_list_unref ( info - > op_list ) ;
if ( info - > op )
meta_draw_op_free ( info - > op ) ;
if ( info - > style )
meta_frame_style_unref ( info - > style ) ;
if ( info - > style_set )
meta_frame_style_set_unref ( info - > style_set ) ;
}
static void
push_state ( ParseInfo * info ,
ParseState state )
{
info - > states = g_slist_prepend ( info - > states , GINT_TO_POINTER ( state ) ) ;
}
static void
pop_state ( ParseInfo * info )
{
g_return_if_fail ( info - > states ! = NULL ) ;
info - > states = g_slist_remove ( info - > states , info - > states - > data ) ;
}
static ParseState
peek_state ( ParseInfo * info )
{
g_return_val_if_fail ( info - > states ! = NULL , STATE_START ) ;
return GPOINTER_TO_INT ( info - > states - > data ) ;
}
# define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0)
typedef struct
{
const char * name ;
const char * * retloc ;
} LocateAttr ;
static gboolean
locate_attributes ( GMarkupParseContext * context ,
const char * element_name ,
const char * * attribute_names ,
const char * * attribute_values ,
GError * * error ,
const char * first_attribute_name ,
const char * * first_attribute_retloc ,
. . . )
{
va_list args ;
const char * name ;
const char * * retloc ;
int n_attrs ;
# define MAX_ATTRS 24
LocateAttr attrs [ MAX_ATTRS ] ;
gboolean retval ;
int i ;
g_return_val_if_fail ( first_attribute_name ! = NULL , FALSE ) ;
g_return_val_if_fail ( first_attribute_retloc ! = NULL , FALSE ) ;
retval = TRUE ;
n_attrs = 1 ;
attrs [ 0 ] . name = first_attribute_name ;
attrs [ 0 ] . retloc = first_attribute_retloc ;
* first_attribute_retloc = NULL ;
va_start ( args , first_attribute_retloc ) ;
name = va_arg ( args , const char * ) ;
retloc = va_arg ( args , const char * * ) ;
while ( name ! = NULL )
{
g_return_val_if_fail ( retloc ! = NULL , FALSE ) ;
2002-02-06 22:25:34 -05:00
g_assert ( n_attrs < MAX_ATTRS ) ;
2002-02-06 22:07:56 -05:00
attrs [ n_attrs ] . name = name ;
attrs [ n_attrs ] . retloc = retloc ;
n_attrs + = 1 ;
* retloc = NULL ;
name = va_arg ( args , const char * ) ;
retloc = va_arg ( args , const char * * ) ;
}
va_end ( args ) ;
if ( ! retval )
return retval ;
i = 0 ;
while ( attribute_names [ i ] )
{
int j ;
gboolean found ;
found = FALSE ;
j = 0 ;
while ( j < n_attrs )
{
if ( strcmp ( attrs [ j ] . name , attribute_names [ i ] ) = = 0 )
{
retloc = attrs [ j ] . retloc ;
if ( * retloc ! = NULL )
{
set_error ( error , context ,
G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Attribute \" %s \" repeated twice on the same <%s> element " ) ,
attrs [ j ] . name , element_name ) ;
retval = FALSE ;
2002-02-06 22:25:34 -05:00
goto out ;
2002-02-06 22:07:56 -05:00
}
* retloc = attribute_values [ i ] ;
found = TRUE ;
}
+ + j ;
}
if ( ! found )
{
set_error ( error , context ,
G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Attribute \" %s \" is invalid on <%s> element in this context " ) ,
attribute_names [ i ] , element_name ) ;
retval = FALSE ;
2002-02-06 22:25:34 -05:00
goto out ;
2002-02-06 22:07:56 -05:00
}
+ + i ;
}
2002-02-06 22:25:34 -05:00
out :
2002-02-06 22:07:56 -05:00
return retval ;
}
static gboolean
check_no_attributes ( GMarkupParseContext * context ,
const char * element_name ,
const char * * attribute_names ,
const char * * attribute_values ,
GError * * error )
{
if ( attribute_names [ 0 ] ! = NULL )
{
set_error ( error , context ,
G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Attribute \" %s \" is invalid on <%s> element in this context " ) ,
attribute_names [ 0 ] , element_name ) ;
return FALSE ;
}
return TRUE ;
}
# define MAX_REASONABLE 4096
static gboolean
parse_positive_integer ( const char * str ,
int * val ,
GMarkupParseContext * context ,
GError * * error )
{
char * end ;
long l ;
* val = 0 ;
end = NULL ;
l = strtol ( str , & end , 10 ) ;
if ( end = = NULL | | end = = str )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Could not parse \" %s \" as an integer " ) ,
str ) ;
return FALSE ;
}
if ( * end ! = ' \0 ' )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand trailing characters \" %s \" in string \" %s \" " ) ,
end , str ) ;
return FALSE ;
}
if ( l < 0 )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Integer %ld must be positive " ) , l ) ;
return FALSE ;
}
if ( l > MAX_REASONABLE )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Integer %ld is too large, current max is %d " ) ,
l , MAX_REASONABLE ) ;
return FALSE ;
}
* val = ( int ) l ;
return TRUE ;
}
static gboolean
parse_double ( const char * str ,
double * val ,
GMarkupParseContext * context ,
GError * * error )
{
char * end ;
* val = 0 ;
end = NULL ;
* val = g_ascii_strtod ( str , & end ) ;
if ( end = = NULL | | end = = str )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Could not parse \" %s \" as a floating point number " ) ,
str ) ;
return FALSE ;
}
if ( * end ! = ' \0 ' )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand trailing characters \" %s \" in string \" %s \" " ) ,
end , str ) ;
return FALSE ;
}
return TRUE ;
}
2002-02-09 12:02:38 -05:00
static gboolean
parse_boolean ( const char * str ,
gboolean * val ,
GMarkupParseContext * context ,
GError * * error )
{
if ( strcmp ( " true " , str ) = = 0 )
* val = TRUE ;
else if ( strcmp ( " false " , str ) = = 0 )
* val = FALSE ;
else
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Boolean values must be \" true \" or \" false \" not \" %s \" " ) ,
str ) ;
return FALSE ;
}
return TRUE ;
}
2002-02-06 22:07:56 -05:00
static gboolean
parse_angle ( const char * str ,
double * val ,
GMarkupParseContext * context ,
GError * * error )
{
if ( ! parse_double ( str , val , context , error ) )
return FALSE ;
if ( * val < ( 0.0 - 1e6 ) | | * val > ( 360.0 + 1e6 ) )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Angle must be between 0.0 and 360.0, was %g \n " ) ,
* val ) ;
return FALSE ;
}
return TRUE ;
}
static gboolean
2002-05-31 17:18:11 -04:00
parse_alpha ( const char * str ,
MetaAlphaGradientSpec * * spec_ret ,
GMarkupParseContext * context ,
GError * * error )
2002-02-06 22:07:56 -05:00
{
2002-05-31 17:18:11 -04:00
char * * split ;
int i ;
int n_alphas ;
MetaAlphaGradientSpec * spec ;
2002-02-06 22:07:56 -05:00
2002-05-31 17:18:11 -04:00
* spec_ret = NULL ;
split = g_strsplit ( str , " : " , - 1 ) ;
i = 0 ;
while ( split [ i ] )
+ + i ;
if ( i = = 0 )
2002-02-06 22:07:56 -05:00
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-05-31 17:18:11 -04:00
_ ( " Could not parse \" %s \" as a floating point number " ) ,
str ) ;
g_strfreev ( split ) ;
2002-02-06 22:07:56 -05:00
return FALSE ;
}
2002-05-31 17:18:11 -04:00
n_alphas = i ;
/* FIXME allow specifying horizontal/vertical/diagonal in theme format,
* once we implement vertical / diagonal in gradient . c
*/
spec = meta_alpha_gradient_spec_new ( META_GRADIENT_HORIZONTAL ,
n_alphas ) ;
i = 0 ;
while ( i < n_alphas )
{
double v ;
if ( ! parse_double ( split [ i ] , & v , context , error ) )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Could not parse \" %s \" as a floating point number " ) ,
split [ i ] ) ;
g_strfreev ( split ) ;
meta_alpha_gradient_spec_free ( spec ) ;
return FALSE ;
}
if ( v < ( 0.0 - 1e6 ) | | v > ( 1.0 + 1e6 ) )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g \n " ) ,
v ) ;
g_strfreev ( split ) ;
meta_alpha_gradient_spec_free ( spec ) ;
return FALSE ;
}
spec - > alphas [ i ] = ( unsigned char ) ( v * 255 ) ;
+ + i ;
}
g_strfreev ( split ) ;
* spec_ret = spec ;
2002-02-06 22:07:56 -05:00
return TRUE ;
}
2002-02-09 12:02:38 -05:00
static gboolean
parse_title_scale ( const char * str ,
double * val ,
GMarkupParseContext * context ,
GError * * error )
{
double factor ;
if ( strcmp ( str , " xx-small " ) = = 0 )
factor = PANGO_SCALE_XX_SMALL ;
else if ( strcmp ( str , " x-small " ) = = 0 )
factor = PANGO_SCALE_X_SMALL ;
else if ( strcmp ( str , " small " ) = = 0 )
factor = PANGO_SCALE_SMALL ;
else if ( strcmp ( str , " medium " ) = = 0 )
factor = PANGO_SCALE_MEDIUM ;
else if ( strcmp ( str , " large " ) = = 0 )
factor = PANGO_SCALE_LARGE ;
else if ( strcmp ( str , " x-large " ) = = 0 )
factor = PANGO_SCALE_X_LARGE ;
else if ( strcmp ( str , " xx-large " ) = = 0 )
factor = PANGO_SCALE_XX_LARGE ;
else
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Invalid title scale \" %s \" (must be one of xx-small,x-small,small,medium,large,x-large,xx-large) \n " ) ,
str ) ;
return FALSE ;
}
* val = factor ;
return TRUE ;
}
2002-02-06 22:07:56 -05:00
static void
parse_toplevel_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
g_return_if_fail ( peek_state ( info ) = = STATE_THEME ) ;
if ( ELEMENT_IS ( " info " ) )
{
if ( ! check_no_attributes ( context , element_name ,
attribute_names , attribute_values ,
error ) )
return ;
push_state ( info , STATE_INFO ) ;
}
else if ( ELEMENT_IS ( " constant " ) )
{
const char * name ;
const char * value ;
int ival ;
double dval ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" name " , & name , " value " , & value ,
NULL ) )
return ;
if ( name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2005-08-08 17:31:31 -04:00
_ ( " No \" %s \" attribute on <%s> element " ) ,
2002-02-09 12:02:38 -05:00
" name " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
2002-02-09 12:02:38 -05:00
2002-02-06 22:07:56 -05:00
if ( value = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2005-08-08 17:31:31 -04:00
_ ( " No \" %s \" attribute on <%s> element " ) ,
2002-02-09 12:02:38 -05:00
" value " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
if ( strchr ( value , ' . ' ) )
{
dval = 0.0 ;
if ( ! parse_double ( value , & dval , context , error ) )
return ;
if ( ! meta_theme_define_float_constant ( info - > theme ,
name ,
dval ,
error ) )
{
add_context_to_error ( error , context ) ;
return ;
}
}
else
{
ival = 0 ;
if ( ! parse_positive_integer ( value , & ival , context , error ) )
return ;
if ( ! meta_theme_define_int_constant ( info - > theme ,
name ,
ival ,
error ) )
{
add_context_to_error ( error , context ) ;
return ;
}
}
push_state ( info , STATE_CONSTANT ) ;
}
else if ( ELEMENT_IS ( " frame_geometry " ) )
{
const char * name = NULL ;
const char * parent = NULL ;
2002-02-09 01:54:44 -05:00
const char * has_title = NULL ;
2002-02-09 12:02:38 -05:00
const char * title_scale = NULL ;
2002-05-30 20:02:54 -04:00
const char * rounded_top_left = NULL ;
const char * rounded_top_right = NULL ;
const char * rounded_bottom_left = NULL ;
const char * rounded_bottom_right = NULL ;
2002-02-09 01:54:44 -05:00
gboolean has_title_val ;
2002-05-30 20:02:54 -04:00
gboolean rounded_top_left_val ;
gboolean rounded_top_right_val ;
gboolean rounded_bottom_left_val ;
gboolean rounded_bottom_right_val ;
2002-02-09 12:02:38 -05:00
double title_scale_val ;
2002-02-06 22:07:56 -05:00
MetaFrameLayout * parent_layout ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" name " , & name , " parent " , & parent ,
2002-02-09 12:02:38 -05:00
" has_title " , & has_title , " title_scale " , & title_scale ,
2002-05-30 20:02:54 -04:00
" rounded_top_left " , & rounded_top_left ,
" rounded_top_right " , & rounded_top_right ,
" rounded_bottom_left " , & rounded_bottom_left ,
" rounded_bottom_right " , & rounded_bottom_right ,
2002-02-06 22:07:56 -05:00
NULL ) )
return ;
if ( name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " No \" %s \" attribute on <%s> element " ) ,
" name " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
2002-02-09 01:54:44 -05:00
has_title_val = TRUE ;
if ( has_title & & ! parse_boolean ( has_title , & has_title_val , context , error ) )
return ;
2002-02-09 12:02:38 -05:00
2002-05-30 20:02:54 -04:00
rounded_top_left_val = FALSE ;
rounded_top_right_val = FALSE ;
rounded_bottom_left_val = FALSE ;
rounded_bottom_right_val = FALSE ;
if ( rounded_top_left & & ! parse_boolean ( rounded_top_left , & rounded_top_left_val , context , error ) )
return ;
if ( rounded_top_right & & ! parse_boolean ( rounded_top_right , & rounded_top_right_val , context , error ) )
return ;
if ( rounded_bottom_left & & ! parse_boolean ( rounded_bottom_left , & rounded_bottom_left_val , context , error ) )
return ;
if ( rounded_bottom_right & & ! parse_boolean ( rounded_bottom_right , & rounded_bottom_right_val , context , error ) )
return ;
2002-02-09 12:02:38 -05:00
title_scale_val = 1.0 ;
if ( title_scale & & ! parse_title_scale ( title_scale , & title_scale_val , context , error ) )
return ;
2002-02-09 01:54:44 -05:00
2002-02-06 22:07:56 -05:00
if ( meta_theme_lookup_layout ( info - > theme , name ) )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " <%s> name \" %s \" used a second time " ) ,
element_name , name ) ;
return ;
}
parent_layout = NULL ;
if ( parent )
{
parent_layout = meta_theme_lookup_layout ( info - > theme , parent ) ;
if ( parent_layout = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " <%s> parent \" %s \" has not been defined " ) ,
element_name , parent ) ;
return ;
}
}
g_assert ( info - > layout = = NULL ) ;
if ( parent_layout )
info - > layout = meta_frame_layout_copy ( parent_layout ) ;
else
info - > layout = meta_frame_layout_new ( ) ;
2002-02-09 01:54:44 -05:00
if ( has_title ) /* only if explicit, otherwise inherit */
info - > layout - > has_title = has_title_val ;
2002-02-09 12:02:38 -05:00
2002-02-11 11:28:17 -05:00
if ( title_scale )
info - > layout - > title_scale = title_scale_val ;
2002-05-30 20:02:54 -04:00
if ( rounded_top_left )
info - > layout - > top_left_corner_rounded = rounded_top_left_val ;
if ( rounded_top_right )
info - > layout - > top_right_corner_rounded = rounded_top_right_val ;
if ( rounded_bottom_left )
info - > layout - > bottom_left_corner_rounded = rounded_bottom_left_val ;
if ( rounded_bottom_right )
info - > layout - > bottom_right_corner_rounded = rounded_bottom_right_val ;
2002-02-09 01:54:44 -05:00
2002-02-06 22:07:56 -05:00
meta_theme_insert_layout ( info - > theme , name , info - > layout ) ;
push_state ( info , STATE_FRAME_GEOMETRY ) ;
}
else if ( ELEMENT_IS ( " draw_ops " ) )
{
const char * name = NULL ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" name " , & name ,
NULL ) )
return ;
if ( name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " No \" %s \" attribute on <%s> element " ) ,
" name " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
if ( meta_theme_lookup_draw_op_list ( info - > theme , name ) )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " <%s> name \" %s \" used a second time " ) ,
element_name , name ) ;
return ;
}
g_assert ( info - > op_list = = NULL ) ;
info - > op_list = meta_draw_op_list_new ( 2 ) ;
meta_theme_insert_draw_op_list ( info - > theme , name , info - > op_list ) ;
push_state ( info , STATE_DRAW_OPS ) ;
}
else if ( ELEMENT_IS ( " frame_style " ) )
{
const char * name = NULL ;
const char * parent = NULL ;
const char * geometry = NULL ;
MetaFrameStyle * parent_style ;
MetaFrameLayout * layout ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" name " , & name , " parent " , & parent ,
" geometry " , & geometry ,
NULL ) )
return ;
if ( name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " No \" %s \" attribute on <%s> element " ) ,
" name " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
if ( meta_theme_lookup_style ( info - > theme , name ) )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " <%s> name \" %s \" used a second time " ) ,
element_name , name ) ;
return ;
}
parent_style = NULL ;
if ( parent )
{
parent_style = meta_theme_lookup_style ( info - > theme , parent ) ;
if ( parent_style = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " <%s> parent \" %s \" has not been defined " ) ,
element_name , parent ) ;
return ;
}
}
layout = NULL ;
if ( geometry )
{
layout = meta_theme_lookup_layout ( info - > theme , geometry ) ;
if ( layout = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " <%s> geometry \" %s \" has not been defined " ) ,
element_name , geometry ) ;
return ;
}
}
else if ( parent_style )
{
layout = parent_style - > layout ;
}
if ( layout = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " <%s> must specify either a geometry or a parent that has a geometry " ) ,
element_name ) ;
return ;
}
g_assert ( info - > style = = NULL ) ;
info - > style = meta_frame_style_new ( parent_style ) ;
g_assert ( info - > style - > layout = = NULL ) ;
meta_frame_layout_ref ( layout ) ;
info - > style - > layout = layout ;
meta_theme_insert_style ( info - > theme , name , info - > style ) ;
push_state ( info , STATE_FRAME_STYLE ) ;
}
else if ( ELEMENT_IS ( " frame_style_set " ) )
{
const char * name = NULL ;
const char * parent = NULL ;
MetaFrameStyleSet * parent_set ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" name " , & name , " parent " , & parent ,
NULL ) )
return ;
if ( name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " No \" %s \" attribute on <%s> element " ) ,
" name " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
if ( meta_theme_lookup_style_set ( info - > theme , name ) )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " <%s> name \" %s \" used a second time " ) ,
element_name , name ) ;
return ;
}
parent_set = NULL ;
if ( parent )
{
parent_set = meta_theme_lookup_style_set ( info - > theme , parent ) ;
if ( parent_set = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " <%s> parent \" %s \" has not been defined " ) ,
element_name , parent ) ;
return ;
}
}
g_assert ( info - > style_set = = NULL ) ;
info - > style_set = meta_frame_style_set_new ( parent_set ) ;
meta_theme_insert_style_set ( info - > theme , name , info - > style_set ) ;
push_state ( info , STATE_FRAME_STYLE_SET ) ;
}
else if ( ELEMENT_IS ( " window " ) )
{
const char * type_name = NULL ;
const char * style_set_name = NULL ;
MetaFrameStyleSet * style_set ;
MetaFrameType type ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" type " , & type_name , " style_set " , & style_set_name ,
NULL ) )
return ;
if ( type_name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " No \" %s \" attribute on <%s> element " ) ,
" type " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
if ( style_set_name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " No \" %s \" attribute on <%s> element " ) ,
" style_set " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
type = meta_frame_type_from_string ( type_name ) ;
if ( type = = META_FRAME_TYPE_LAST )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Unknown type \" %s \" on <%s> element " ) ,
type_name , element_name ) ;
return ;
}
style_set = meta_theme_lookup_style_set ( info - > theme ,
style_set_name ) ;
if ( style_set = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Unknown style_set \" %s \" on <%s> element " ) ,
style_set_name , element_name ) ;
return ;
}
if ( info - > theme - > style_sets_by_type [ type ] ! = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Window type \" %s \" has already been assigned a style set " ) ,
type_name ) ;
return ;
}
meta_frame_style_set_ref ( style_set ) ;
info - > theme - > style_sets_by_type [ type ] = style_set ;
push_state ( info , STATE_WINDOW ) ;
}
else if ( ELEMENT_IS ( " menu_icon " ) )
{
const char * function = NULL ;
const char * state = NULL ;
const char * draw_ops = NULL ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" function " , & function ,
" state " , & state ,
" draw_ops " , & draw_ops ,
NULL ) )
return ;
if ( function = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " No \" %s \" attribute on <%s> element " ) ,
" function " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
if ( state = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " No \" %s \" attribute on <%s> element " ) ,
" state " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
info - > menu_icon_type = meta_menu_icon_type_from_string ( function ) ;
if ( info - > menu_icon_type = = META_BUTTON_TYPE_LAST )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Unknown function \" %s \" for menu icon " ) ,
function ) ;
return ;
}
info - > menu_icon_state = meta_gtk_state_from_string ( state ) ;
if ( ( ( int ) info - > menu_icon_state ) = = - 1 )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Unknown state \" %s \" for menu icon " ) ,
state ) ;
return ;
}
if ( info - > theme - > menu_icons [ info - > menu_icon_type ] [ info - > menu_icon_state ] ! = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Theme already has a menu icon for function %s state %s " ) ,
function , state ) ;
return ;
}
g_assert ( info - > op_list = = NULL ) ;
if ( draw_ops )
{
MetaDrawOpList * op_list ;
op_list = meta_theme_lookup_draw_op_list ( info - > theme ,
draw_ops ) ;
if ( op_list = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No <draw_ops> with the name \" %s \" has been defined " ) ,
draw_ops ) ;
return ;
}
meta_draw_op_list_ref ( op_list ) ;
info - > op_list = op_list ;
}
push_state ( info , STATE_MENU_ICON ) ;
}
else
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed below <%s> " ) ,
element_name , " metacity_theme " ) ;
2002-02-06 22:07:56 -05:00
}
}
static void
parse_info_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
g_return_if_fail ( peek_state ( info ) = = STATE_INFO ) ;
if ( ELEMENT_IS ( " name " ) )
{
if ( ! check_no_attributes ( context , element_name ,
attribute_names , attribute_values ,
error ) )
return ;
push_state ( info , STATE_NAME ) ;
}
else if ( ELEMENT_IS ( " author " ) )
{
if ( ! check_no_attributes ( context , element_name ,
attribute_names , attribute_values ,
error ) )
return ;
push_state ( info , STATE_AUTHOR ) ;
}
else if ( ELEMENT_IS ( " copyright " ) )
{
if ( ! check_no_attributes ( context , element_name ,
attribute_names , attribute_values ,
error ) )
return ;
push_state ( info , STATE_COPYRIGHT ) ;
}
else if ( ELEMENT_IS ( " description " ) )
{
if ( ! check_no_attributes ( context , element_name ,
attribute_names , attribute_values ,
error ) )
return ;
push_state ( info , STATE_DESCRIPTION ) ;
}
else if ( ELEMENT_IS ( " date " ) )
{
if ( ! check_no_attributes ( context , element_name ,
attribute_names , attribute_values ,
error ) )
return ;
push_state ( info , STATE_DATE ) ;
}
else
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed below <%s> " ) ,
element_name , " info " ) ;
2002-02-06 22:07:56 -05:00
}
}
static void
parse_distance ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
const char * name ;
const char * value ;
int val ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" name " , & name , " value " , & value ,
NULL ) )
return ;
if ( name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" name \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( value = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" value \" attribute on element <%s> " ) , element_name ) ;
return ;
}
val = 0 ;
if ( ! parse_positive_integer ( value , & val , context , error ) )
return ;
g_assert ( val > = 0 ) ; /* yeah, "non-negative" not "positive" get over it */
g_assert ( info - > layout ) ;
if ( strcmp ( name , " left_width " ) = = 0 )
info - > layout - > left_width = val ;
else if ( strcmp ( name , " right_width " ) = = 0 )
info - > layout - > right_width = val ;
else if ( strcmp ( name , " bottom_height " ) = = 0 )
info - > layout - > bottom_height = val ;
else if ( strcmp ( name , " title_vertical_pad " ) = = 0 )
info - > layout - > title_vertical_pad = val ;
else if ( strcmp ( name , " right_titlebar_edge " ) = = 0 )
info - > layout - > right_titlebar_edge = val ;
else if ( strcmp ( name , " left_titlebar_edge " ) = = 0 )
info - > layout - > left_titlebar_edge = val ;
else if ( strcmp ( name , " button_width " ) = = 0 )
2002-06-03 22:13:00 -04:00
{
info - > layout - > button_width = val ;
if ( ! ( info - > layout - > button_sizing = = META_BUTTON_SIZING_LAST | |
info - > layout - > button_sizing = = META_BUTTON_SIZING_FIXED ) )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Cannot specify both button_width/button_height and aspect ratio for buttons " ) ) ;
return ;
}
info - > layout - > button_sizing = META_BUTTON_SIZING_FIXED ;
}
2002-02-06 22:07:56 -05:00
else if ( strcmp ( name , " button_height " ) = = 0 )
2002-06-03 22:13:00 -04:00
{
info - > layout - > button_height = val ;
if ( ! ( info - > layout - > button_sizing = = META_BUTTON_SIZING_LAST | |
info - > layout - > button_sizing = = META_BUTTON_SIZING_FIXED ) )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Cannot specify both button_width/button_height and aspect ratio for buttons " ) ) ;
return ;
}
info - > layout - > button_sizing = META_BUTTON_SIZING_FIXED ;
}
else
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Distance \" %s \" is unknown " ) , name ) ;
return ;
}
}
static void
parse_aspect_ratio ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
const char * name ;
const char * value ;
double val ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" name " , & name , " value " , & value ,
NULL ) )
return ;
if ( name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" name \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( value = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" value \" attribute on element <%s> " ) , element_name ) ;
return ;
}
val = 0 ;
if ( ! parse_double ( value , & val , context , error ) )
return ;
g_assert ( info - > layout ) ;
if ( strcmp ( name , " button " ) = = 0 )
{
info - > layout - > button_aspect = val ;
if ( info - > layout - > button_sizing ! = META_BUTTON_SIZING_LAST )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Cannot specify both button_width/button_height and aspect ratio for buttons " ) ) ;
return ;
}
info - > layout - > button_sizing = META_BUTTON_SIZING_ASPECT ;
}
2002-02-06 22:07:56 -05:00
else
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-06-03 22:15:38 -04:00
_ ( " Aspect ratio \" %s \" is unknown " ) , name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
}
static void
parse_border ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
const char * name ;
const char * top ;
const char * bottom ;
const char * left ;
const char * right ;
int top_val ;
int bottom_val ;
int left_val ;
int right_val ;
GtkBorder * border ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" name " , & name ,
" top " , & top ,
" bottom " , & bottom ,
" left " , & left ,
" right " , & right ,
NULL ) )
return ;
if ( name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" name \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( top = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" top \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( bottom = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" bottom \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( left = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" left \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( right = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" right \" attribute on element <%s> " ) , element_name ) ;
return ;
}
top_val = 0 ;
if ( ! parse_positive_integer ( top , & top_val , context , error ) )
return ;
bottom_val = 0 ;
if ( ! parse_positive_integer ( bottom , & bottom_val , context , error ) )
return ;
left_val = 0 ;
if ( ! parse_positive_integer ( left , & left_val , context , error ) )
return ;
right_val = 0 ;
if ( ! parse_positive_integer ( right , & right_val , context , error ) )
return ;
g_assert ( info - > layout ) ;
border = NULL ;
if ( strcmp ( name , " title_border " ) = = 0 )
border = & info - > layout - > title_border ;
else if ( strcmp ( name , " button_border " ) = = 0 )
border = & info - > layout - > button_border ;
if ( border = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Border \" %s \" is unknown " ) , name ) ;
return ;
}
border - > top = top_val ;
border - > bottom = bottom_val ;
border - > left = left_val ;
border - > right = right_val ;
}
static void
parse_geometry_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
g_return_if_fail ( peek_state ( info ) = = STATE_FRAME_GEOMETRY ) ;
if ( ELEMENT_IS ( " distance " ) )
{
parse_distance ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
push_state ( info , STATE_DISTANCE ) ;
}
else if ( ELEMENT_IS ( " border " ) )
{
parse_border ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
push_state ( info , STATE_BORDER ) ;
}
2002-06-03 22:13:00 -04:00
else if ( ELEMENT_IS ( " aspect_ratio " ) )
{
parse_aspect_ratio ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
push_state ( info , STATE_ASPECT_RATIO ) ;
}
2002-02-06 22:07:56 -05:00
else
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed below <%s> " ) ,
element_name , " frame_geometry " ) ;
2002-02-06 22:07:56 -05:00
}
}
static gboolean
check_expression ( const char * expr ,
gboolean has_object ,
MetaTheme * theme ,
GMarkupParseContext * context ,
GError * * error )
{
MetaPositionExprEnv env ;
int x , y ;
/* We set it all to 0 to try and catch divide-by-zero screwups.
* it ' s possible we should instead guarantee that widths and heights
* are at least 1.
*/
env . x = 0 ;
env . y = 0 ;
env . width = 0 ;
env . height = 0 ;
if ( has_object )
{
env . object_width = 0 ;
env . object_height = 0 ;
}
else
{
env . object_width = - 1 ;
env . object_height = - 1 ;
}
env . left_width = 0 ;
env . right_width = 0 ;
env . top_height = 0 ;
env . bottom_height = 0 ;
env . title_width = 0 ;
env . title_height = 0 ;
env . icon_width = 0 ;
env . icon_height = 0 ;
env . mini_icon_width = 0 ;
env . mini_icon_height = 0 ;
env . theme = theme ;
if ( ! meta_parse_position_expression ( expr ,
& env ,
& x , & y ,
error ) )
{
add_context_to_error ( error , context ) ;
return FALSE ;
}
return TRUE ;
}
static char *
optimize_expression ( MetaTheme * theme ,
const char * expr )
{
/* We aren't expecting an error here, since we already
* did check_expression
*/
return meta_theme_replace_constants ( theme , expr , NULL ) ;
}
static void
parse_draw_op_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
g_return_if_fail ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
if ( ELEMENT_IS ( " line " ) )
{
MetaDrawOp * op ;
const char * color ;
const char * x1 ;
const char * y1 ;
const char * x2 ;
const char * y2 ;
const char * dash_on_length ;
const char * dash_off_length ;
const char * width ;
MetaColorSpec * color_spec ;
int dash_on_val ;
int dash_off_val ;
int width_val ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" color " , & color ,
" x1 " , & x1 , " y1 " , & y1 ,
" x2 " , & x2 , " y2 " , & y2 ,
" dash_on_length " , & dash_on_length ,
" dash_off_length " , & dash_off_length ,
" width " , & width ,
NULL ) )
return ;
if ( color = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" color \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( x1 = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x1 \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y1 = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y1 \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( x2 = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x2 \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y2 = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y2 \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x1 , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y1 , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( x2 , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y2 , FALSE , info - > theme , context , error ) )
return ;
dash_on_val = 0 ;
if ( dash_on_length & &
! parse_positive_integer ( dash_on_length , & dash_on_val , context , error ) )
return ;
dash_off_val = 0 ;
if ( dash_off_length & &
! parse_positive_integer ( dash_off_length , & dash_off_val , context , error ) )
return ;
width_val = 0 ;
if ( width & &
! parse_positive_integer ( width , & width_val , context , error ) )
return ;
/* Check last so we don't have to free it when other
* stuff fails
*/
color_spec = meta_color_spec_new_from_string ( color , error ) ;
if ( color_spec = = NULL )
{
add_context_to_error ( error , context ) ;
return ;
}
op = meta_draw_op_new ( META_DRAW_LINE ) ;
op - > data . line . color_spec = color_spec ;
op - > data . line . x1 = optimize_expression ( info - > theme , x1 ) ;
op - > data . line . y1 = optimize_expression ( info - > theme , y1 ) ;
op - > data . line . x2 = optimize_expression ( info - > theme , x2 ) ;
op - > data . line . y2 = optimize_expression ( info - > theme , y2 ) ;
op - > data . line . width = width_val ;
op - > data . line . dash_on_length = dash_on_val ;
op - > data . line . dash_off_length = dash_off_val ;
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_LINE ) ;
}
else if ( ELEMENT_IS ( " rectangle " ) )
{
MetaDrawOp * op ;
const char * color ;
const char * x ;
const char * y ;
const char * width ;
const char * height ;
const char * filled ;
gboolean filled_val ;
MetaColorSpec * color_spec ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" color " , & color ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
" filled " , & filled ,
NULL ) )
return ;
if ( color = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" color \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( width = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" width \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( height = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" height \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( width , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( height , FALSE , info - > theme , context , error ) )
return ;
filled_val = FALSE ;
if ( filled & & ! parse_boolean ( filled , & filled_val , context , error ) )
return ;
/* Check last so we don't have to free it when other
* stuff fails
*/
color_spec = meta_color_spec_new_from_string ( color , error ) ;
if ( color_spec = = NULL )
{
add_context_to_error ( error , context ) ;
return ;
}
op = meta_draw_op_new ( META_DRAW_RECTANGLE ) ;
op - > data . rectangle . color_spec = color_spec ;
op - > data . rectangle . x = optimize_expression ( info - > theme , x ) ;
op - > data . rectangle . y = optimize_expression ( info - > theme , y ) ;
op - > data . rectangle . width = optimize_expression ( info - > theme , width ) ;
op - > data . rectangle . height = optimize_expression ( info - > theme , height ) ;
op - > data . rectangle . filled = filled_val ;
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_RECTANGLE ) ;
}
else if ( ELEMENT_IS ( " arc " ) )
{
MetaDrawOp * op ;
const char * color ;
const char * x ;
const char * y ;
const char * width ;
const char * height ;
const char * filled ;
const char * start_angle ;
const char * extent_angle ;
gboolean filled_val ;
double start_angle_val ;
double extent_angle_val ;
MetaColorSpec * color_spec ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" color " , & color ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
" filled " , & filled ,
" start_angle " , & start_angle ,
" extent_angle " , & extent_angle ,
NULL ) )
return ;
if ( color = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" color \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( width = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" width \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( height = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" height \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( start_angle = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" start_angle \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( extent_angle = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" extent_angle \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( width , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( height , FALSE , info - > theme , context , error ) )
return ;
if ( ! parse_angle ( start_angle , & start_angle_val , context , error ) )
return ;
if ( ! parse_angle ( extent_angle , & extent_angle_val , context , error ) )
return ;
filled_val = FALSE ;
if ( filled & & ! parse_boolean ( filled , & filled_val , context , error ) )
return ;
/* Check last so we don't have to free it when other
* stuff fails
*/
color_spec = meta_color_spec_new_from_string ( color , error ) ;
if ( color_spec = = NULL )
{
add_context_to_error ( error , context ) ;
return ;
}
op = meta_draw_op_new ( META_DRAW_ARC ) ;
op - > data . arc . color_spec = color_spec ;
op - > data . arc . x = optimize_expression ( info - > theme , x ) ;
op - > data . arc . y = optimize_expression ( info - > theme , y ) ;
op - > data . arc . width = optimize_expression ( info - > theme , width ) ;
op - > data . arc . height = optimize_expression ( info - > theme , height ) ;
op - > data . arc . filled = filled_val ;
op - > data . arc . start_angle = start_angle_val ;
op - > data . arc . extent_angle = extent_angle_val ;
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_ARC ) ;
}
else if ( ELEMENT_IS ( " clip " ) )
{
MetaDrawOp * op ;
const char * x ;
const char * y ;
const char * width ;
const char * height ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
NULL ) )
return ;
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( width = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" width \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( height = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" height \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( width , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( height , FALSE , info - > theme , context , error ) )
return ;
op = meta_draw_op_new ( META_DRAW_CLIP ) ;
op - > data . clip . x = optimize_expression ( info - > theme , x ) ;
op - > data . clip . y = optimize_expression ( info - > theme , y ) ;
op - > data . clip . width = optimize_expression ( info - > theme , width ) ;
op - > data . clip . height = optimize_expression ( info - > theme , height ) ;
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_CLIP ) ;
}
else if ( ELEMENT_IS ( " tint " ) )
{
MetaDrawOp * op ;
const char * color ;
const char * x ;
const char * y ;
const char * width ;
const char * height ;
const char * alpha ;
2002-05-31 17:18:11 -04:00
MetaAlphaGradientSpec * alpha_spec ;
2002-02-06 22:07:56 -05:00
MetaColorSpec * color_spec ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" color " , & color ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
" alpha " , & alpha ,
NULL ) )
return ;
if ( color = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" color \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( width = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" width \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( height = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" height \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( alpha = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" alpha \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( width , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( height , FALSE , info - > theme , context , error ) )
return ;
2002-05-31 17:18:11 -04:00
alpha_spec = NULL ;
if ( ! parse_alpha ( alpha , & alpha_spec , context , error ) )
2002-02-06 22:07:56 -05:00
return ;
/* Check last so we don't have to free it when other
* stuff fails
*/
color_spec = meta_color_spec_new_from_string ( color , error ) ;
if ( color_spec = = NULL )
{
2002-05-31 17:18:11 -04:00
if ( alpha_spec )
meta_alpha_gradient_spec_free ( alpha_spec ) ;
2002-02-06 22:07:56 -05:00
add_context_to_error ( error , context ) ;
return ;
}
op = meta_draw_op_new ( META_DRAW_TINT ) ;
op - > data . tint . color_spec = color_spec ;
2002-05-31 17:18:11 -04:00
op - > data . tint . alpha_spec = alpha_spec ;
2002-02-06 22:07:56 -05:00
op - > data . tint . x = optimize_expression ( info - > theme , x ) ;
op - > data . tint . y = optimize_expression ( info - > theme , y ) ;
op - > data . tint . width = optimize_expression ( info - > theme , width ) ;
op - > data . tint . height = optimize_expression ( info - > theme , height ) ;
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_TINT ) ;
}
else if ( ELEMENT_IS ( " gradient " ) )
{
const char * x ;
const char * y ;
const char * width ;
const char * height ;
const char * type ;
const char * alpha ;
2002-05-31 17:18:11 -04:00
MetaAlphaGradientSpec * alpha_spec ;
2002-02-06 22:07:56 -05:00
MetaGradientType type_val ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" type " , & type ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
" alpha " , & alpha ,
NULL ) )
return ;
if ( type = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" type \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( width = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" width \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( height = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" height \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( width , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( height , FALSE , info - > theme , context , error ) )
return ;
type_val = meta_gradient_type_from_string ( type ) ;
if ( type_val = = META_GRADIENT_LAST )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand value \" %s \" for type of gradient " ) ,
type ) ;
return ;
}
2002-05-31 17:18:11 -04:00
alpha_spec = NULL ;
if ( alpha & & ! parse_alpha ( alpha , & alpha_spec , context , error ) )
return ;
2002-02-06 22:07:56 -05:00
g_assert ( info - > op = = NULL ) ;
info - > op = meta_draw_op_new ( META_DRAW_GRADIENT ) ;
info - > op - > data . gradient . x = optimize_expression ( info - > theme , x ) ;
info - > op - > data . gradient . y = optimize_expression ( info - > theme , y ) ;
info - > op - > data . gradient . width = optimize_expression ( info - > theme , width ) ;
info - > op - > data . gradient . height = optimize_expression ( info - > theme , height ) ;
2002-05-31 17:18:11 -04:00
info - > op - > data . gradient . gradient_spec = meta_gradient_spec_new ( type_val ) ;
2002-02-06 22:07:56 -05:00
2002-05-31 17:18:11 -04:00
info - > op - > data . gradient . alpha_spec = alpha_spec ;
2002-02-06 22:07:56 -05:00
push_state ( info , STATE_GRADIENT ) ;
/* op gets appended on close tag */
}
else if ( ELEMENT_IS ( " image " ) )
{
MetaDrawOp * op ;
const char * filename ;
const char * x ;
const char * y ;
const char * width ;
const char * height ;
const char * alpha ;
2002-02-06 22:43:13 -05:00
const char * colorize ;
2002-05-31 18:03:34 -04:00
const char * fill_type ;
2002-05-31 17:18:11 -04:00
MetaAlphaGradientSpec * alpha_spec ;
2002-02-06 22:07:56 -05:00
GdkPixbuf * pixbuf ;
2002-02-06 22:43:13 -05:00
MetaColorSpec * colorize_spec = NULL ;
2002-05-31 18:03:34 -04:00
MetaImageFillType fill_type_val ;
2002-11-04 12:55:56 -05:00
int h , w , c ;
int pixbuf_width , pixbuf_height , pixbuf_n_channels , pixbuf_rowstride ;
guchar * pixbuf_pixels ;
2002-02-06 22:07:56 -05:00
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
" alpha " , & alpha , " filename " , & filename ,
2002-02-06 22:43:13 -05:00
" colorize " , & colorize ,
2002-05-31 18:03:34 -04:00
" fill_type " , & fill_type ,
2002-02-06 22:07:56 -05:00
NULL ) )
return ;
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( width = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" width \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( height = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" height \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( filename = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" filename \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , TRUE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y , TRUE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( width , TRUE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( height , TRUE , info - > theme , context , error ) )
return ;
2002-05-31 18:03:34 -04:00
fill_type_val = META_IMAGE_FILL_SCALE ;
if ( fill_type )
{
fill_type_val = meta_image_fill_type_from_string ( fill_type ) ;
2002-11-04 12:55:56 -05:00
2002-05-31 18:03:34 -04:00
if ( ( ( int ) fill_type_val ) = = - 1 )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand fill type \" %s \" for <%s> element " ) ,
fill_type , element_name ) ;
}
}
2002-02-06 22:07:56 -05:00
/* Check last so we don't have to free it when other
* stuff fails
*/
pixbuf = meta_theme_load_image ( info - > theme , filename , error ) ;
if ( pixbuf = = NULL )
{
add_context_to_error ( error , context ) ;
return ;
}
2002-02-06 22:43:13 -05:00
if ( colorize )
2002-11-04 12:55:56 -05:00
{
colorize_spec = meta_color_spec_new_from_string ( colorize , error ) ;
if ( colorize_spec = = NULL )
{
add_context_to_error ( error , context ) ;
2002-02-06 23:22:57 -05:00
g_object_unref ( G_OBJECT ( pixbuf ) ) ;
2002-11-04 12:55:56 -05:00
return ;
}
}
2002-05-31 17:18:11 -04:00
alpha_spec = NULL ;
if ( alpha & & ! parse_alpha ( alpha , & alpha_spec , context , error ) )
{
g_object_unref ( G_OBJECT ( pixbuf ) ) ;
return ;
}
2002-02-06 22:07:56 -05:00
op = meta_draw_op_new ( META_DRAW_IMAGE ) ;
op - > data . image . pixbuf = pixbuf ;
2002-02-06 22:43:13 -05:00
op - > data . image . colorize_spec = colorize_spec ;
2002-02-06 22:07:56 -05:00
op - > data . image . x = optimize_expression ( info - > theme , x ) ;
op - > data . image . y = optimize_expression ( info - > theme , y ) ;
op - > data . image . width = optimize_expression ( info - > theme , width ) ;
op - > data . image . height = optimize_expression ( info - > theme , height ) ;
2002-05-31 17:18:11 -04:00
op - > data . image . alpha_spec = alpha_spec ;
2002-05-31 18:03:34 -04:00
op - > data . image . fill_type = fill_type_val ;
2002-11-04 12:55:56 -05:00
/* Check for vertical & horizontal stripes */
pixbuf_n_channels = gdk_pixbuf_get_n_channels ( pixbuf ) ;
pixbuf_width = gdk_pixbuf_get_width ( pixbuf ) ;
pixbuf_height = gdk_pixbuf_get_height ( pixbuf ) ;
pixbuf_rowstride = gdk_pixbuf_get_rowstride ( pixbuf ) ;
pixbuf_pixels = gdk_pixbuf_get_pixels ( pixbuf ) ;
/* Check for horizontal stripes */
for ( h = 0 ; h < pixbuf_height ; h + + )
{
for ( w = 1 ; w < pixbuf_width ; w + + )
{
for ( c = 0 ; c < pixbuf_n_channels ; c + + )
{
if ( pixbuf_pixels [ ( h * pixbuf_rowstride ) + c ] ! =
pixbuf_pixels [ ( h * pixbuf_rowstride ) + w + c ] )
break ;
}
if ( c < pixbuf_n_channels )
break ;
}
if ( w < pixbuf_width )
break ;
}
if ( h > = pixbuf_height )
{
op - > data . image . horizontal_stripes = TRUE ;
}
else
{
op - > data . image . horizontal_stripes = FALSE ;
}
/* Check for vertical stripes */
for ( w = 0 ; w < pixbuf_width ; w + + )
{
for ( h = 1 ; h < pixbuf_height ; h + + )
{
for ( c = 0 ; c < pixbuf_n_channels ; c + + )
{
if ( pixbuf_pixels [ w + c ] ! =
pixbuf_pixels [ ( h * pixbuf_rowstride ) + w + c ] )
break ;
}
if ( c < pixbuf_n_channels )
break ;
}
if ( h < pixbuf_height )
break ;
}
if ( w > = pixbuf_width )
{
op - > data . image . vertical_stripes = TRUE ;
}
else
{
op - > data . image . vertical_stripes = FALSE ;
}
2002-02-06 22:07:56 -05:00
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_IMAGE ) ;
}
else if ( ELEMENT_IS ( " gtk_arrow " ) )
{
MetaDrawOp * op ;
const char * state ;
const char * shadow ;
const char * arrow ;
const char * x ;
const char * y ;
const char * width ;
const char * height ;
const char * filled ;
gboolean filled_val ;
GtkStateType state_val ;
GtkShadowType shadow_val ;
GtkArrowType arrow_val ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" state " , & state ,
" shadow " , & shadow ,
" arrow " , & arrow ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
" filled " , & filled ,
NULL ) )
return ;
if ( state = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" state \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( shadow = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" shadow \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( arrow = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" arrow \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( width = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" width \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( height = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" height \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( width , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( height , FALSE , info - > theme , context , error ) )
return ;
filled_val = TRUE ;
if ( filled & & ! parse_boolean ( filled , & filled_val , context , error ) )
return ;
state_val = meta_gtk_state_from_string ( state ) ;
if ( ( ( int ) state_val ) = = - 1 )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand state \" %s \" for <%s> element " ) ,
state , element_name ) ;
return ;
}
shadow_val = meta_gtk_shadow_from_string ( shadow ) ;
if ( ( ( int ) shadow_val ) = = - 1 )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand shadow \" %s \" for <%s> element " ) ,
shadow , element_name ) ;
return ;
}
arrow_val = meta_gtk_arrow_from_string ( arrow ) ;
if ( ( ( int ) arrow_val ) = = - 1 )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand arrow \" %s \" for <%s> element " ) ,
arrow , element_name ) ;
return ;
}
op = meta_draw_op_new ( META_DRAW_GTK_ARROW ) ;
op - > data . gtk_arrow . x = optimize_expression ( info - > theme , x ) ;
op - > data . gtk_arrow . y = optimize_expression ( info - > theme , y ) ;
op - > data . gtk_arrow . width = optimize_expression ( info - > theme , width ) ;
op - > data . gtk_arrow . height = optimize_expression ( info - > theme , height ) ;
op - > data . gtk_arrow . filled = filled_val ;
op - > data . gtk_arrow . state = state_val ;
op - > data . gtk_arrow . shadow = shadow_val ;
op - > data . gtk_arrow . arrow = arrow_val ;
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_GTK_ARROW ) ;
}
else if ( ELEMENT_IS ( " gtk_box " ) )
{
MetaDrawOp * op ;
const char * state ;
const char * shadow ;
const char * x ;
const char * y ;
const char * width ;
const char * height ;
GtkStateType state_val ;
GtkShadowType shadow_val ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" state " , & state ,
" shadow " , & shadow ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
NULL ) )
return ;
if ( state = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" state \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( shadow = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" shadow \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( width = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" width \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( height = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" height \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( width , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( height , FALSE , info - > theme , context , error ) )
return ;
state_val = meta_gtk_state_from_string ( state ) ;
if ( ( ( int ) state_val ) = = - 1 )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand state \" %s \" for <%s> element " ) ,
state , element_name ) ;
return ;
}
shadow_val = meta_gtk_shadow_from_string ( shadow ) ;
if ( ( ( int ) shadow_val ) = = - 1 )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand shadow \" %s \" for <%s> element " ) ,
shadow , element_name ) ;
return ;
}
op = meta_draw_op_new ( META_DRAW_GTK_BOX ) ;
op - > data . gtk_box . x = optimize_expression ( info - > theme , x ) ;
op - > data . gtk_box . y = optimize_expression ( info - > theme , y ) ;
op - > data . gtk_box . width = optimize_expression ( info - > theme , width ) ;
op - > data . gtk_box . height = optimize_expression ( info - > theme , height ) ;
op - > data . gtk_box . state = state_val ;
op - > data . gtk_box . shadow = shadow_val ;
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_GTK_BOX ) ;
}
else if ( ELEMENT_IS ( " gtk_vline " ) )
{
MetaDrawOp * op ;
const char * state ;
const char * x ;
const char * y1 ;
const char * y2 ;
GtkStateType state_val ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" state " , & state ,
" x " , & x , " y1 " , & y1 , " y2 " , & y2 ,
NULL ) )
return ;
if ( state = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" state \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y1 = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y1 \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y2 = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y2 \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y1 , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y2 , FALSE , info - > theme , context , error ) )
return ;
state_val = meta_gtk_state_from_string ( state ) ;
if ( ( ( int ) state_val ) = = - 1 )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand state \" %s \" for <%s> element " ) ,
state , element_name ) ;
return ;
}
op = meta_draw_op_new ( META_DRAW_GTK_VLINE ) ;
op - > data . gtk_vline . x = optimize_expression ( info - > theme , x ) ;
op - > data . gtk_vline . y1 = optimize_expression ( info - > theme , y1 ) ;
op - > data . gtk_vline . y2 = optimize_expression ( info - > theme , y2 ) ;
op - > data . gtk_vline . state = state_val ;
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_GTK_VLINE ) ;
}
else if ( ELEMENT_IS ( " icon " ) )
{
MetaDrawOp * op ;
const char * x ;
const char * y ;
const char * width ;
const char * height ;
const char * alpha ;
2002-05-31 18:03:34 -04:00
const char * fill_type ;
2002-05-31 17:18:11 -04:00
MetaAlphaGradientSpec * alpha_spec ;
2002-05-31 18:03:34 -04:00
MetaImageFillType fill_type_val ;
2002-02-06 22:07:56 -05:00
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
" alpha " , & alpha ,
2002-05-31 18:03:34 -04:00
" fill_type " , & fill_type ,
2002-02-06 22:07:56 -05:00
NULL ) )
return ;
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( width = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" width \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( height = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" height \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( width , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( height , FALSE , info - > theme , context , error ) )
return ;
2002-05-31 18:03:34 -04:00
fill_type_val = META_IMAGE_FILL_SCALE ;
if ( fill_type )
{
fill_type_val = meta_image_fill_type_from_string ( fill_type ) ;
if ( ( ( int ) fill_type_val ) = = - 1 )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Did not understand fill type \" %s \" for <%s> element " ) ,
fill_type , element_name ) ;
}
}
2002-05-31 17:18:11 -04:00
alpha_spec = NULL ;
if ( alpha & & ! parse_alpha ( alpha , & alpha_spec , context , error ) )
2002-02-06 22:07:56 -05:00
return ;
op = meta_draw_op_new ( META_DRAW_ICON ) ;
op - > data . icon . x = optimize_expression ( info - > theme , x ) ;
op - > data . icon . y = optimize_expression ( info - > theme , y ) ;
op - > data . icon . width = optimize_expression ( info - > theme , width ) ;
op - > data . icon . height = optimize_expression ( info - > theme , height ) ;
2002-05-31 17:18:11 -04:00
op - > data . icon . alpha_spec = alpha_spec ;
2002-05-31 18:03:34 -04:00
op - > data . icon . fill_type = fill_type_val ;
2002-02-06 22:07:56 -05:00
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_ICON ) ;
}
else if ( ELEMENT_IS ( " title " ) )
{
MetaDrawOp * op ;
const char * color ;
const char * x ;
const char * y ;
MetaColorSpec * color_spec ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" color " , & color ,
" x " , & x , " y " , & y ,
NULL ) )
return ;
if ( color = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" color \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( x = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" x \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( y = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" y \" attribute on element <%s> " ) , element_name ) ;
return ;
}
if ( ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
/* Check last so we don't have to free it when other
* stuff fails
*/
color_spec = meta_color_spec_new_from_string ( color , error ) ;
if ( color_spec = = NULL )
{
add_context_to_error ( error , context ) ;
return ;
}
op = meta_draw_op_new ( META_DRAW_TITLE ) ;
op - > data . title . color_spec = color_spec ;
op - > data . title . x = optimize_expression ( info - > theme , x ) ;
op - > data . title . y = optimize_expression ( info - > theme , y ) ;
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_TITLE ) ;
}
else if ( ELEMENT_IS ( " include " ) )
{
MetaDrawOp * op ;
const char * name ;
const char * x ;
const char * y ;
const char * width ;
const char * height ;
MetaDrawOpList * op_list ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
" name " , & name ,
NULL ) )
return ;
if ( name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2005-08-08 17:31:31 -04:00
_ ( " No \" %s \" attribute on <%s> element " ) , " name " , element_name ) ;
2002-02-06 22:07:56 -05:00
return ;
}
/* x/y/width/height default to 0,0,width,height - should
* probably do this for all the draw ops
*/
if ( x & & ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( y & & ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
if ( width & & ! check_expression ( width , FALSE , info - > theme , context , error ) )
return ;
if ( height & & ! check_expression ( height , FALSE , info - > theme , context , error ) )
return ;
op_list = meta_theme_lookup_draw_op_list ( info - > theme ,
name ) ;
if ( op_list = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " No <draw_ops> called \" %s \" has been defined " ) ,
name ) ;
return ;
}
g_assert ( info - > op_list ) ;
if ( op_list = = info - > op_list | |
meta_draw_op_list_contains ( op_list , info - > op_list ) )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Including draw_ops \" %s \" here would create a circular reference " ) ,
name ) ;
return ;
}
op = meta_draw_op_new ( META_DRAW_OP_LIST ) ;
meta_draw_op_list_ref ( op_list ) ;
op - > data . op_list . op_list = op_list ;
op - > data . op_list . x = x ? optimize_expression ( info - > theme , x ) :
g_strdup ( " 0 " ) ;
op - > data . op_list . y = y ? optimize_expression ( info - > theme , y ) :
g_strdup ( " 0 " ) ;
op - > data . op_list . width = width ? optimize_expression ( info - > theme , width ) :
g_strdup ( " width " ) ;
op - > data . op_list . height = height ? optimize_expression ( info - > theme , height ) :
g_strdup ( " height " ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_INCLUDE ) ;
}
2002-02-09 20:10:33 -05:00
else if ( ELEMENT_IS ( " tile " ) )
{
MetaDrawOp * op ;
const char * name ;
const char * x ;
const char * y ;
const char * width ;
const char * height ;
const char * tile_xoffset ;
const char * tile_yoffset ;
const char * tile_width ;
const char * tile_height ;
MetaDrawOpList * op_list ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" x " , & x , " y " , & y ,
" width " , & width , " height " , & height ,
" name " , & name ,
" tile_xoffset " , & tile_xoffset ,
" tile_yoffset " , & tile_yoffset ,
" tile_width " , & tile_width ,
" tile_height " , & tile_height ,
NULL ) )
return ;
if ( name = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2005-08-08 17:31:31 -04:00
_ ( " No \" %s \" attribute on <%s> element " ) , " name " , element_name ) ;
2002-02-09 20:10:33 -05:00
return ;
}
if ( tile_width = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2005-08-08 17:31:31 -04:00
_ ( " No \" %s \" attribute on <%s> element " ) , " tile_width " , element_name ) ;
2002-02-09 20:10:33 -05:00
return ;
}
if ( tile_height = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2005-08-08 17:31:31 -04:00
_ ( " No \" %s \" attribute on <%s> element " ) , " tile_height " , element_name ) ;
2002-02-09 20:10:33 -05:00
return ;
}
/* These default to 0 */
if ( tile_xoffset & & ! check_expression ( tile_xoffset , FALSE , info - > theme , context , error ) )
return ;
if ( tile_yoffset & & ! check_expression ( tile_xoffset , FALSE , info - > theme , context , error ) )
return ;
/* x/y/width/height default to 0,0,width,height - should
* probably do this for all the draw ops
*/
if ( x & & ! check_expression ( x , FALSE , info - > theme , context , error ) )
return ;
if ( y & & ! check_expression ( y , FALSE , info - > theme , context , error ) )
return ;
if ( width & & ! check_expression ( width , FALSE , info - > theme , context , error ) )
return ;
if ( height & & ! check_expression ( height , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( tile_width , FALSE , info - > theme , context , error ) )
return ;
if ( ! check_expression ( tile_height , FALSE , info - > theme , context , error ) )
return ;
op_list = meta_theme_lookup_draw_op_list ( info - > theme ,
name ) ;
if ( op_list = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " No <draw_ops> called \" %s \" has been defined " ) ,
name ) ;
return ;
}
g_assert ( info - > op_list ) ;
if ( op_list = = info - > op_list | |
meta_draw_op_list_contains ( op_list , info - > op_list ) )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " Including draw_ops \" %s \" here would create a circular reference " ) ,
name ) ;
return ;
}
op = meta_draw_op_new ( META_DRAW_TILE ) ;
meta_draw_op_list_ref ( op_list ) ;
op - > data . tile . op_list = op_list ;
op - > data . tile . x = x ? optimize_expression ( info - > theme , x ) :
g_strdup ( " 0 " ) ;
op - > data . tile . y = y ? optimize_expression ( info - > theme , y ) :
g_strdup ( " 0 " ) ;
op - > data . tile . width = width ? optimize_expression ( info - > theme , width ) :
g_strdup ( " width " ) ;
op - > data . tile . height = height ? optimize_expression ( info - > theme , height ) :
g_strdup ( " height " ) ;
op - > data . tile . tile_xoffset = tile_xoffset ?
optimize_expression ( info - > theme , tile_xoffset ) :
g_strdup ( " 0 " ) ;
op - > data . tile . tile_yoffset = tile_yoffset ?
optimize_expression ( info - > theme , tile_yoffset ) :
g_strdup ( " 0 " ) ;
op - > data . tile . tile_width = optimize_expression ( info - > theme , tile_width ) ;
op - > data . tile . tile_height = optimize_expression ( info - > theme , tile_height ) ;
meta_draw_op_list_append ( info - > op_list , op ) ;
push_state ( info , STATE_TILE ) ;
}
2002-02-06 22:07:56 -05:00
else
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed below <%s> " ) ,
element_name , " draw_ops " ) ;
2002-02-06 22:07:56 -05:00
}
}
static void
parse_gradient_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
g_return_if_fail ( peek_state ( info ) = = STATE_GRADIENT ) ;
if ( ELEMENT_IS ( " color " ) )
{
const char * value = NULL ;
MetaColorSpec * color_spec ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" value " , & value ,
NULL ) )
return ;
if ( value = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" value \" attribute on <%s> element " ) ,
element_name ) ;
return ;
}
color_spec = meta_color_spec_new_from_string ( value , error ) ;
if ( color_spec = = NULL )
{
add_context_to_error ( error , context ) ;
return ;
}
g_assert ( info - > op ) ;
g_assert ( info - > op - > type = = META_DRAW_GRADIENT ) ;
g_assert ( info - > op - > data . gradient . gradient_spec ! = NULL ) ;
info - > op - > data . gradient . gradient_spec - > color_specs =
g_slist_append ( info - > op - > data . gradient . gradient_spec - > color_specs ,
color_spec ) ;
push_state ( info , STATE_COLOR ) ;
}
else
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed below <%s> " ) ,
element_name , " gradient " ) ;
2002-02-06 22:07:56 -05:00
}
}
static void
parse_style_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
g_return_if_fail ( peek_state ( info ) = = STATE_FRAME_STYLE ) ;
g_assert ( info - > style ) ;
if ( ELEMENT_IS ( " piece " ) )
{
const char * position = NULL ;
const char * draw_ops = NULL ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" position " , & position ,
" draw_ops " , & draw_ops ,
NULL ) )
return ;
if ( position = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" position \" attribute on <%s> element " ) ,
element_name ) ;
return ;
}
info - > piece = meta_frame_piece_from_string ( position ) ;
if ( info - > piece = = META_FRAME_PIECE_LAST )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Unknown position \" %s \" for frame piece " ) ,
position ) ;
return ;
}
if ( info - > style - > pieces [ info - > piece ] ! = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Frame style already has a piece at position %s " ) ,
position ) ;
return ;
}
g_assert ( info - > op_list = = NULL ) ;
if ( draw_ops )
{
MetaDrawOpList * op_list ;
op_list = meta_theme_lookup_draw_op_list ( info - > theme ,
draw_ops ) ;
if ( op_list = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No <draw_ops> with the name \" %s \" has been defined " ) ,
draw_ops ) ;
return ;
}
meta_draw_op_list_ref ( op_list ) ;
info - > op_list = op_list ;
}
push_state ( info , STATE_PIECE ) ;
}
else if ( ELEMENT_IS ( " button " ) )
{
const char * function = NULL ;
const char * state = NULL ;
const char * draw_ops = NULL ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" function " , & function ,
" state " , & state ,
" draw_ops " , & draw_ops ,
NULL ) )
return ;
if ( function = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" function \" attribute on <%s> element " ) ,
element_name ) ;
return ;
}
if ( state = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" state \" attribute on <%s> element " ) ,
element_name ) ;
return ;
}
info - > button_type = meta_button_type_from_string ( function ) ;
if ( info - > button_type = = META_BUTTON_TYPE_LAST )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Unknown function \" %s \" for button " ) ,
function ) ;
return ;
}
info - > button_state = meta_button_state_from_string ( state ) ;
if ( info - > button_state = = META_BUTTON_STATE_LAST )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Unknown state \" %s \" for button " ) ,
state ) ;
return ;
}
if ( info - > style - > buttons [ info - > button_type ] [ info - > button_state ] ! = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Frame style already has a button for function %s state %s " ) ,
function , state ) ;
return ;
}
g_assert ( info - > op_list = = NULL ) ;
if ( draw_ops )
{
MetaDrawOpList * op_list ;
op_list = meta_theme_lookup_draw_op_list ( info - > theme ,
draw_ops ) ;
if ( op_list = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No <draw_ops> with the name \" %s \" has been defined " ) ,
draw_ops ) ;
return ;
}
meta_draw_op_list_ref ( op_list ) ;
info - > op_list = op_list ;
}
push_state ( info , STATE_BUTTON ) ;
}
else
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed below <%s> " ) ,
element_name , " frame_style " ) ;
2002-02-06 22:07:56 -05:00
}
}
static void
parse_style_set_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
g_return_if_fail ( peek_state ( info ) = = STATE_FRAME_STYLE_SET ) ;
if ( ELEMENT_IS ( " frame " ) )
{
const char * focus = NULL ;
const char * state = NULL ;
const char * resize = NULL ;
const char * style = NULL ;
MetaFrameFocus frame_focus ;
MetaFrameState frame_state ;
MetaFrameResize frame_resize ;
MetaFrameStyle * frame_style ;
if ( ! locate_attributes ( context , element_name , attribute_names , attribute_values ,
error ,
" focus " , & focus ,
" state " , & state ,
" resize " , & resize ,
" style " , & style ,
NULL ) )
return ;
if ( focus = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" focus \" attribute on <%s> element " ) ,
element_name ) ;
return ;
}
if ( state = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" state \" attribute on <%s> element " ) ,
element_name ) ;
return ;
}
if ( style = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" style \" attribute on <%s> element " ) ,
element_name ) ;
return ;
}
frame_focus = meta_frame_focus_from_string ( focus ) ;
if ( frame_focus = = META_FRAME_FOCUS_LAST )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " \" %s \" is not a valid value for focus attribute " ) ,
focus ) ;
return ;
}
frame_state = meta_frame_state_from_string ( state ) ;
if ( frame_state = = META_FRAME_STATE_LAST )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " \" %s \" is not a valid value for state attribute " ) ,
focus ) ;
return ;
}
frame_style = meta_theme_lookup_style ( info - > theme , style ) ;
if ( frame_style = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " A style called \" %s \" has not been defined " ) ,
style ) ;
return ;
}
if ( frame_state = = META_FRAME_STATE_NORMAL )
{
if ( resize = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No \" resize \" attribute on <%s> element " ) ,
element_name ) ;
return ;
}
frame_resize = meta_frame_resize_from_string ( resize ) ;
if ( frame_resize = = META_FRAME_RESIZE_LAST )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " \" %s \" is not a valid value for resize attribute " ) ,
focus ) ;
return ;
}
}
else
{
if ( resize ! = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Should not have \" resize \" attribute on <%s> element for maximized/shaded states " ) ,
element_name ) ;
return ;
}
frame_resize = META_FRAME_RESIZE_LAST ;
}
switch ( frame_state )
{
case META_FRAME_STATE_NORMAL :
if ( info - > style_set - > normal_styles [ frame_resize ] [ frame_focus ] )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Style has already been specified for state %s resize %s focus %s " ) ,
state , resize , focus ) ;
return ;
}
meta_frame_style_ref ( frame_style ) ;
info - > style_set - > normal_styles [ frame_resize ] [ frame_focus ] = frame_style ;
break ;
case META_FRAME_STATE_MAXIMIZED :
if ( info - > style_set - > maximized_styles [ frame_focus ] )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Style has already been specified for state %s focus %s " ) ,
state , focus ) ;
return ;
}
meta_frame_style_ref ( frame_style ) ;
info - > style_set - > maximized_styles [ frame_focus ] = frame_style ;
break ;
case META_FRAME_STATE_SHADED :
if ( info - > style_set - > shaded_styles [ frame_focus ] )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Style has already been specified for state %s focus %s " ) ,
state , focus ) ;
return ;
}
meta_frame_style_ref ( frame_style ) ;
info - > style_set - > shaded_styles [ frame_focus ] = frame_style ;
break ;
case META_FRAME_STATE_MAXIMIZED_AND_SHADED :
if ( info - > style_set - > maximized_and_shaded_styles [ frame_focus ] )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Style has already been specified for state %s focus %s " ) ,
state , focus ) ;
return ;
}
meta_frame_style_ref ( frame_style ) ;
info - > style_set - > maximized_and_shaded_styles [ frame_focus ] = frame_style ;
break ;
case META_FRAME_STATE_LAST :
g_assert_not_reached ( ) ;
break ;
}
push_state ( info , STATE_FRAME ) ;
}
else
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed below <%s> " ) ,
element_name , " frame_style_set " ) ;
2002-02-06 22:07:56 -05:00
}
}
static void
parse_piece_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
g_return_if_fail ( peek_state ( info ) = = STATE_PIECE ) ;
if ( ELEMENT_IS ( " draw_ops " ) )
{
if ( info - > op_list )
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Can't have a two draw_ops for a <piece> element (theme specified a draw_ops attribute and also a <draw_ops> element, or specified two elements) " ) ) ;
return ;
}
if ( ! check_no_attributes ( context , element_name , attribute_names , attribute_values ,
error ) )
return ;
g_assert ( info - > op_list = = NULL ) ;
info - > op_list = meta_draw_op_list_new ( 2 ) ;
push_state ( info , STATE_DRAW_OPS ) ;
}
else
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed below <%s> " ) ,
element_name , " piece " ) ;
2002-02-06 22:07:56 -05:00
}
}
static void
parse_button_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
g_return_if_fail ( peek_state ( info ) = = STATE_BUTTON ) ;
if ( ELEMENT_IS ( " draw_ops " ) )
{
if ( info - > op_list )
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Can't have a two draw_ops for a <button> element (theme specified a draw_ops attribute and also a <draw_ops> element, or specified two elements) " ) ) ;
return ;
}
if ( ! check_no_attributes ( context , element_name , attribute_names , attribute_values ,
error ) )
return ;
g_assert ( info - > op_list = = NULL ) ;
info - > op_list = meta_draw_op_list_new ( 2 ) ;
push_state ( info , STATE_DRAW_OPS ) ;
}
else
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed below <%s> " ) ,
element_name , " button " ) ;
2002-02-06 22:07:56 -05:00
}
}
static void
parse_menu_icon_element ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
ParseInfo * info ,
GError * * error )
{
g_return_if_fail ( peek_state ( info ) = = STATE_MENU_ICON ) ;
if ( ELEMENT_IS ( " draw_ops " ) )
{
if ( info - > op_list )
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Can't have a two draw_ops for a <menu_icon> element (theme specified a draw_ops attribute and also a <draw_ops> element, or specified two elements) " ) ) ;
return ;
}
if ( ! check_no_attributes ( context , element_name , attribute_names , attribute_values ,
error ) )
return ;
g_assert ( info - > op_list = = NULL ) ;
info - > op_list = meta_draw_op_list_new ( 2 ) ;
push_state ( info , STATE_DRAW_OPS ) ;
}
else
{
set_error ( error , context ,
G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed below <%s> " ) ,
element_name , " menu_icon " ) ;
2002-02-06 22:07:56 -05:00
}
}
static void
start_element_handler ( GMarkupParseContext * context ,
const gchar * element_name ,
const gchar * * attribute_names ,
const gchar * * attribute_values ,
gpointer user_data ,
GError * * error )
{
ParseInfo * info = user_data ;
switch ( peek_state ( info ) )
{
case STATE_START :
if ( strcmp ( element_name , " metacity_theme " ) = = 0 )
{
info - > theme = meta_theme_new ( ) ;
info - > theme - > name = g_strdup ( info - > theme_name ) ;
info - > theme - > filename = g_strdup ( info - > theme_file ) ;
info - > theme - > dirname = g_strdup ( info - > theme_dir ) ;
push_state ( info , STATE_THEME ) ;
}
else
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Outermost element in theme must be <metacity_theme> not <%s> " ) ,
element_name ) ;
break ;
case STATE_THEME :
parse_toplevel_element ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
break ;
case STATE_INFO :
parse_info_element ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
break ;
case STATE_NAME :
case STATE_AUTHOR :
case STATE_COPYRIGHT :
case STATE_DATE :
case STATE_DESCRIPTION :
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Element <%s> is not allowed inside a name/author/date/description element " ) ,
element_name ) ;
break ;
case STATE_CONSTANT :
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Element <%s> is not allowed inside a <constant> element " ) ,
element_name ) ;
break ;
case STATE_FRAME_GEOMETRY :
parse_geometry_element ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
break ;
case STATE_DISTANCE :
case STATE_BORDER :
2002-06-03 22:13:00 -04:00
case STATE_ASPECT_RATIO :
2002-02-06 22:07:56 -05:00
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-06-03 22:13:00 -04:00
_ ( " Element <%s> is not allowed inside a distance/border/aspect_ratio element " ) ,
2002-02-06 22:07:56 -05:00
element_name ) ;
break ;
case STATE_DRAW_OPS :
parse_draw_op_element ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
break ;
case STATE_LINE :
case STATE_RECTANGLE :
case STATE_ARC :
case STATE_CLIP :
case STATE_TINT :
case STATE_IMAGE :
case STATE_GTK_ARROW :
case STATE_GTK_BOX :
case STATE_GTK_VLINE :
case STATE_ICON :
case STATE_TITLE :
case STATE_INCLUDE :
2002-02-09 20:10:33 -05:00
case STATE_TILE :
2002-02-06 22:07:56 -05:00
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Element <%s> is not allowed inside a draw operation element " ) ,
element_name ) ;
break ;
case STATE_GRADIENT :
parse_gradient_element ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
break ;
case STATE_COLOR :
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed inside a <%s> element " ) ,
element_name , " color " ) ;
2002-02-06 22:07:56 -05:00
break ;
case STATE_FRAME_STYLE :
parse_style_element ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
break ;
case STATE_PIECE :
parse_piece_element ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
break ;
case STATE_BUTTON :
parse_button_element ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
break ;
case STATE_MENU_ICON :
parse_menu_icon_element ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
break ;
case STATE_FRAME_STYLE_SET :
parse_style_set_element ( context , element_name ,
attribute_names , attribute_values ,
info , error ) ;
break ;
case STATE_FRAME :
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed inside a <%s> element " ) ,
element_name , " frame " ) ;
2002-02-06 22:07:56 -05:00
break ;
case STATE_WINDOW :
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
2002-02-09 12:02:38 -05:00
_ ( " Element <%s> is not allowed inside a <%s> element " ) ,
element_name , " window " ) ;
2002-02-06 22:07:56 -05:00
break ;
}
}
static void
end_element_handler ( GMarkupParseContext * context ,
const gchar * element_name ,
gpointer user_data ,
GError * * error )
{
ParseInfo * info = user_data ;
switch ( peek_state ( info ) )
{
case STATE_START :
break ;
case STATE_THEME :
g_assert ( info - > theme ) ;
if ( ! meta_theme_validate ( info - > theme , error ) )
{
add_context_to_error ( error , context ) ;
meta_theme_free ( info - > theme ) ;
info - > theme = NULL ;
}
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_START ) ;
break ;
case STATE_INFO :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_THEME ) ;
break ;
case STATE_NAME :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_INFO ) ;
break ;
case STATE_AUTHOR :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_INFO ) ;
break ;
case STATE_COPYRIGHT :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_INFO ) ;
break ;
case STATE_DATE :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_INFO ) ;
break ;
case STATE_DESCRIPTION :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_INFO ) ;
break ;
case STATE_CONSTANT :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_THEME ) ;
break ;
case STATE_FRAME_GEOMETRY :
g_assert ( info - > layout ) ;
if ( ! meta_frame_layout_validate ( info - > layout ,
error ) )
{
add_context_to_error ( error , context ) ;
}
/* layout will already be stored in the theme under
* its name
*/
meta_frame_layout_unref ( info - > layout ) ;
info - > layout = NULL ;
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_THEME ) ;
break ;
case STATE_DISTANCE :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_FRAME_GEOMETRY ) ;
break ;
case STATE_BORDER :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_FRAME_GEOMETRY ) ;
break ;
2002-06-03 22:13:00 -04:00
case STATE_ASPECT_RATIO :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_FRAME_GEOMETRY ) ;
break ;
2002-02-06 22:07:56 -05:00
case STATE_DRAW_OPS :
{
g_assert ( info - > op_list ) ;
if ( ! meta_draw_op_list_validate ( info - > op_list ,
error ) )
{
add_context_to_error ( error , context ) ;
meta_draw_op_list_unref ( info - > op_list ) ;
info - > op_list = NULL ;
}
pop_state ( info ) ;
switch ( peek_state ( info ) )
{
case STATE_BUTTON :
case STATE_PIECE :
case STATE_MENU_ICON :
/* Leave info->op_list to be picked up
* when these elements are closed
*/
g_assert ( info - > op_list ) ;
break ;
case STATE_THEME :
g_assert ( info - > op_list ) ;
meta_draw_op_list_unref ( info - > op_list ) ;
info - > op_list = NULL ;
break ;
default :
/* Op list can't occur in other contexts */
g_assert_not_reached ( ) ;
break ;
}
}
break ;
case STATE_LINE :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_RECTANGLE :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_ARC :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_CLIP :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_TINT :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_GRADIENT :
g_assert ( info - > op ) ;
g_assert ( info - > op - > type = = META_DRAW_GRADIENT ) ;
if ( ! meta_gradient_spec_validate ( info - > op - > data . gradient . gradient_spec ,
error ) )
{
add_context_to_error ( error , context ) ;
meta_draw_op_free ( info - > op ) ;
info - > op = NULL ;
}
else
{
g_assert ( info - > op_list ) ;
meta_draw_op_list_append ( info - > op_list , info - > op ) ;
info - > op = NULL ;
}
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_IMAGE :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_GTK_ARROW :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_GTK_BOX :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_GTK_VLINE :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_ICON :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_TITLE :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
case STATE_INCLUDE :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
2002-02-09 20:10:33 -05:00
case STATE_TILE :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_DRAW_OPS ) ;
break ;
2002-02-06 22:07:56 -05:00
case STATE_COLOR :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_GRADIENT ) ;
break ;
case STATE_FRAME_STYLE :
g_assert ( info - > style ) ;
if ( ! meta_frame_style_validate ( info - > style ,
error ) )
{
add_context_to_error ( error , context ) ;
}
/* Frame style is in the theme hash table and a ref
* is held there
*/
meta_frame_style_unref ( info - > style ) ;
info - > style = NULL ;
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_THEME ) ;
break ;
case STATE_PIECE :
g_assert ( info - > style ) ;
if ( info - > op_list = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No draw_ops provided for frame piece " ) ) ;
}
else
{
info - > style - > pieces [ info - > piece ] = info - > op_list ;
info - > op_list = NULL ;
}
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_FRAME_STYLE ) ;
break ;
case STATE_BUTTON :
g_assert ( info - > style ) ;
if ( info - > op_list = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No draw_ops provided for button " ) ) ;
}
else
{
info - > style - > buttons [ info - > button_type ] [ info - > button_state ] =
info - > op_list ;
info - > op_list = NULL ;
}
pop_state ( info ) ;
break ;
case STATE_MENU_ICON :
g_assert ( info - > theme ) ;
if ( info - > op_list = = NULL )
{
set_error ( error , context , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " No draw_ops provided for menu icon " ) ) ;
}
else
{
g_assert ( info - > theme - > menu_icons [ info - > menu_icon_type ] [ info - > menu_icon_state ] = = NULL ) ;
info - > theme - > menu_icons [ info - > menu_icon_type ] [ info - > menu_icon_state ] =
info - > op_list ;
info - > op_list = NULL ;
}
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_THEME ) ;
break ;
case STATE_FRAME_STYLE_SET :
g_assert ( info - > style_set ) ;
if ( ! meta_frame_style_set_validate ( info - > style_set ,
error ) )
{
add_context_to_error ( error , context ) ;
}
/* Style set is in the theme hash table and a reference
* is held there .
*/
meta_frame_style_set_unref ( info - > style_set ) ;
info - > style_set = NULL ;
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_THEME ) ;
break ;
case STATE_FRAME :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_FRAME_STYLE_SET ) ;
break ;
case STATE_WINDOW :
pop_state ( info ) ;
g_assert ( peek_state ( info ) = = STATE_THEME ) ;
break ;
}
}
# define NO_TEXT(element_name) set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, _("No text is allowed inside element <%s>"), element_name)
static gboolean
all_whitespace ( const char * text ,
int text_len )
{
const char * p ;
const char * end ;
p = text ;
end = text + text_len ;
while ( p ! = end )
{
if ( ! g_ascii_isspace ( * p ) )
return FALSE ;
p = g_utf8_next_char ( p ) ;
}
return TRUE ;
}
static void
text_handler ( GMarkupParseContext * context ,
const gchar * text ,
gsize text_len ,
gpointer user_data ,
GError * * error )
{
ParseInfo * info = user_data ;
if ( all_whitespace ( text , text_len ) )
return ;
/* FIXME http://bugzilla.gnome.org/show_bug.cgi?id=70448 would
* allow a nice cleanup here .
*/
switch ( peek_state ( info ) )
{
case STATE_START :
g_assert_not_reached ( ) ; /* gmarkup shouldn't do this */
break ;
case STATE_THEME :
NO_TEXT ( " metacity_theme " ) ;
break ;
case STATE_INFO :
NO_TEXT ( " info " ) ;
break ;
case STATE_NAME :
if ( info - > theme - > readable_name ! = NULL )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " <name> specified twice for this theme " ) ) ;
return ;
}
info - > theme - > readable_name = g_strndup ( text , text_len ) ;
break ;
case STATE_AUTHOR :
if ( info - > theme - > author ! = NULL )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " <author> specified twice for this theme " ) ) ;
return ;
}
info - > theme - > author = g_strndup ( text , text_len ) ;
break ;
case STATE_COPYRIGHT :
if ( info - > theme - > copyright ! = NULL )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " <copyright> specified twice for this theme " ) ) ;
return ;
}
info - > theme - > copyright = g_strndup ( text , text_len ) ;
break ;
case STATE_DATE :
if ( info - > theme - > date ! = NULL )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " <date> specified twice for this theme " ) ) ;
return ;
}
info - > theme - > date = g_strndup ( text , text_len ) ;
break ;
case STATE_DESCRIPTION :
if ( info - > theme - > description ! = NULL )
{
set_error ( error , context , G_MARKUP_ERROR ,
G_MARKUP_ERROR_PARSE ,
_ ( " <description> specified twice for this theme " ) ) ;
return ;
}
info - > theme - > description = g_strndup ( text , text_len ) ;
break ;
case STATE_CONSTANT :
NO_TEXT ( " constant " ) ;
break ;
case STATE_FRAME_GEOMETRY :
NO_TEXT ( " frame_geometry " ) ;
break ;
case STATE_DISTANCE :
NO_TEXT ( " distance " ) ;
break ;
case STATE_BORDER :
NO_TEXT ( " border " ) ;
break ;
2002-06-03 22:13:00 -04:00
case STATE_ASPECT_RATIO :
NO_TEXT ( " aspect_ratio " ) ;
break ;
2002-02-06 22:07:56 -05:00
case STATE_DRAW_OPS :
NO_TEXT ( " draw_ops " ) ;
break ;
case STATE_LINE :
NO_TEXT ( " line " ) ;
break ;
case STATE_RECTANGLE :
NO_TEXT ( " rectangle " ) ;
break ;
case STATE_ARC :
NO_TEXT ( " arc " ) ;
break ;
case STATE_CLIP :
NO_TEXT ( " clip " ) ;
break ;
case STATE_TINT :
NO_TEXT ( " tint " ) ;
break ;
case STATE_GRADIENT :
NO_TEXT ( " gradient " ) ;
break ;
case STATE_IMAGE :
NO_TEXT ( " image " ) ;
break ;
case STATE_GTK_ARROW :
NO_TEXT ( " gtk_arrow " ) ;
break ;
case STATE_GTK_BOX :
NO_TEXT ( " gtk_box " ) ;
break ;
case STATE_GTK_VLINE :
NO_TEXT ( " gtk_vline " ) ;
break ;
case STATE_ICON :
NO_TEXT ( " icon " ) ;
break ;
case STATE_TITLE :
NO_TEXT ( " title " ) ;
break ;
case STATE_INCLUDE :
NO_TEXT ( " include " ) ;
break ;
2002-02-09 20:10:33 -05:00
case STATE_TILE :
NO_TEXT ( " tile " ) ;
break ;
2002-02-06 22:07:56 -05:00
case STATE_COLOR :
NO_TEXT ( " color " ) ;
break ;
case STATE_FRAME_STYLE :
NO_TEXT ( " frame_style " ) ;
break ;
case STATE_PIECE :
NO_TEXT ( " piece " ) ;
break ;
case STATE_BUTTON :
NO_TEXT ( " button " ) ;
break ;
case STATE_MENU_ICON :
NO_TEXT ( " menu_icon " ) ;
break ;
case STATE_FRAME_STYLE_SET :
NO_TEXT ( " frame_style_set " ) ;
break ;
case STATE_FRAME :
NO_TEXT ( " frame " ) ;
break ;
case STATE_WINDOW :
NO_TEXT ( " window " ) ;
break ;
}
}
/* We change the filename when we break the format,
* so themes can work with various metacity versions
2002-07-24 14:28:56 -04:00
* ( note , this is obsolete now because we are versioning
* the directory this file is inside , so oh well )
2002-02-06 22:07:56 -05:00
*/
# define THEME_FILENAME "metacity-theme-1.xml"
2002-07-24 14:28:56 -04:00
/* now this is versioned, /usr/share/themes/NAME/THEME_SUBDIR/THEME_FILENAME */
# define THEME_SUBDIR "metacity-1"
2002-02-06 22:07:56 -05:00
MetaTheme *
meta_theme_load ( const char * theme_name ,
GError * * err )
{
GMarkupParseContext * context ;
GError * error ;
ParseInfo info ;
char * text ;
2003-05-30 00:52:12 -04:00
gsize length ;
2002-02-06 22:07:56 -05:00
char * theme_file ;
char * theme_dir ;
MetaTheme * retval ;
text = NULL ;
length = 0 ;
retval = NULL ;
2003-05-16 17:59:08 -04:00
context = NULL ;
2002-02-06 22:07:56 -05:00
theme_dir = NULL ;
theme_file = NULL ;
if ( meta_is_debugging ( ) )
{
2002-07-24 14:28:56 -04:00
/* Try in themes in our source tree */
2002-02-06 22:07:56 -05:00
theme_dir = g_build_filename ( " ./themes " , theme_name , NULL ) ;
theme_file = g_build_filename ( theme_dir ,
THEME_FILENAME ,
NULL ) ;
error = NULL ;
if ( ! g_file_get_contents ( theme_file ,
& text ,
& length ,
& error ) )
{
2002-02-07 22:34:26 -05:00
meta_topic ( META_DEBUG_THEMES , " Failed to read theme from file %s: %s \n " ,
theme_file , error - > message ) ;
2002-02-06 22:07:56 -05:00
g_error_free ( error ) ;
g_free ( theme_dir ) ;
g_free ( theme_file ) ;
theme_file = NULL ;
}
}
2002-07-24 14:28:56 -04:00
/* We try in home dir, then system dir for themes */
2002-02-06 22:07:56 -05:00
if ( text = = NULL )
{
theme_dir = g_build_filename ( g_get_home_dir ( ) ,
2002-07-24 14:28:56 -04:00
" .themes " ,
theme_name ,
THEME_SUBDIR ,
NULL ) ;
2002-02-06 22:07:56 -05:00
theme_file = g_build_filename ( theme_dir ,
THEME_FILENAME ,
NULL ) ;
error = NULL ;
if ( ! g_file_get_contents ( theme_file ,
& text ,
& length ,
& error ) )
{
2002-02-07 22:34:26 -05:00
meta_topic ( META_DEBUG_THEMES , " Failed to read theme from file %s: %s \n " ,
theme_file , error - > message ) ;
2002-02-06 22:07:56 -05:00
g_error_free ( error ) ;
g_free ( theme_dir ) ;
g_free ( theme_file ) ;
theme_file = NULL ;
}
}
if ( text = = NULL )
{
2002-07-24 14:28:56 -04:00
theme_dir = g_build_filename ( METACITY_DATADIR ,
2002-02-06 22:07:56 -05:00
" themes " ,
2002-07-24 14:28:56 -04:00
theme_name ,
THEME_SUBDIR ,
NULL ) ;
2002-02-06 22:07:56 -05:00
theme_file = g_build_filename ( theme_dir ,
THEME_FILENAME ,
NULL ) ;
error = NULL ;
if ( ! g_file_get_contents ( theme_file ,
& text ,
& length ,
& error ) )
{
meta_warning ( _ ( " Failed to read theme from file %s: %s \n " ) ,
theme_file , error - > message ) ;
g_propagate_error ( err , error ) ;
g_free ( theme_file ) ;
g_free ( theme_dir ) ;
A load of fixes of issues reported by sparse. Closes bug #152849
2004-09-17 Kjartan Maraas <kmaraas@gnome.org>
* src/bell.c: (meta_bell_flash_screen):
* src/compositor.c:
* src/effects.c: (meta_effects_draw_box_animation):
* src/fixedtip.c: (meta_fixed_tip_show):
* src/frame.c: (find_argb_visual):
* src/frames.c: (unsigned_long_hash), (meta_frames_manage_window),
(meta_frames_apply_shapes):
* src/iconcache.c: (find_largest_sizes), (find_best_size):
* src/keybindings.c: (meta_spawn_command_line_async_on_screen):
* src/main.c: (main):
* src/menu.c: (meta_window_menu_new):
* src/prefs.c: (meta_prefs_get_visual_bell),
(meta_prefs_bell_is_audible), (meta_prefs_get_visual_bell_type),
(meta_prefs_get_action_double_click_titlebar),
(meta_prefs_get_auto_raise), (meta_prefs_get_auto_raise_delay),
(meta_prefs_get_reduced_resources):
* src/screen.c: (meta_create_offscreen_window):
* src/tabpopup.c: (meta_ui_tab_popup_get_selected):
* src/theme-parser.c: (meta_theme_load):
* src/theme.c: (meta_gtk_widget_get_font_desc):
* src/tools/metacity-mag.c: (mouse_press), (begin_area_grab):
* src/util.c: (meta_unsigned_long_hash): A load of fixes of issues
reported by sparse. Closes bug #152849
2004-09-16 19:18:22 -04:00
return NULL ; /* all fallbacks failed */
2002-02-06 22:07:56 -05:00
}
}
g_assert ( text ) ;
2002-02-07 22:34:26 -05:00
meta_topic ( META_DEBUG_THEMES , " Parsing theme file %s \n " , theme_file ) ;
2002-02-06 22:07:56 -05:00
parse_info_init ( & info ) ;
info . theme_name = theme_name ;
/* pass ownership to info so we free it with the info */
info . theme_file = theme_file ;
info . theme_dir = theme_dir ;
context = g_markup_parse_context_new ( & metacity_theme_parser ,
0 , & info , NULL ) ;
error = NULL ;
if ( ! g_markup_parse_context_parse ( context ,
text ,
length ,
& error ) )
goto out ;
error = NULL ;
if ( ! g_markup_parse_context_end_parse ( context , & error ) )
goto out ;
goto out ;
out :
2003-05-16 17:59:08 -04:00
if ( context )
g_markup_parse_context_free ( context ) ;
2002-02-06 22:07:56 -05:00
g_free ( text ) ;
if ( error )
{
g_propagate_error ( err , error ) ;
}
else if ( info . theme )
{
/* Steal theme from info */
retval = info . theme ;
info . theme = NULL ;
}
else
{
g_set_error ( err , G_MARKUP_ERROR , G_MARKUP_ERROR_PARSE ,
_ ( " Theme file %s did not contain a root <metacity_theme> element " ) ,
info . theme_file ) ;
}
parse_info_free ( & info ) ;
return retval ;
}