grim/gplate
Clone
Summary
Browse
Changes
Graph
I thought I already added this.. my bad
trying_to_get_includes_working
2008-02-20, grim
545b7214a0de
I thought I already added this.. my bad
/*
* Copyright (C) 2007-2008 Gary Kramlich <grim@reaperworld.com>
*
* 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., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifdef HAVE_CONFIG_H
#
include
<config.h>
#endif
/* HAVE_CONFIG_H */
#include
<gplate/gplate-template.h>
#include
<gplate/gplate-collection.h>
#include
<gplate/gplate-dictionary-variable.h>
#include
<gplate/gplate-errors.h>
#include
<gplate/gplate-library.h>
#include
<gplate/gplate-util.h>
#include
<stdio.h>
#include
<string.h>
#define GPLATE_TEMPLATE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), GPLATE_TYPE_TEMPLATE, GPlateTemplatePrivate))
/******************************************************************************
* Enums
*****************************************************************************/
/******************************************************************************
* Structs
*****************************************************************************/
typedef
struct
{
GPlateVariable
*
vars
;
GList
*
tokens
;
GList
*
current_token
;
}
GPlateTemplatePrivate
;
/******************************************************************************
* Globals
*****************************************************************************/
static
GObjectClass
*
parent_class
=
NULL
;
/******************************************************************************
* Collection Stuff
*****************************************************************************/
static
GPlateVariable
*
gplate_template_find_variable
(
const
GPlateCollection
*
collection
,
const
gchar
*
name
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
collection
);
return
gplate_collection_find_variable
(
GPLATE_COLLECTION
(
priv
->
vars
),
name
);
}
static
gboolean
gplate_template_add_variable
(
GPlateCollection
*
collection
,
GPlateVariable
*
variable
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
collection
);
return
gplate_collection_add_variable
(
GPLATE_COLLECTION
(
priv
->
vars
),
variable
);
}
static
void
gplate_template_collection_init
(
GPlateCollectionIface
*
iface
)
{
iface
->
find_variable
=
gplate_template_find_variable
;
iface
->
add_variable
=
gplate_template_add_variable
;
}
/******************************************************************************
* Template Stuff
*****************************************************************************/
static
void
gplate_template_update_pattern_helper
(
GType
tag
,
const
gchar
*
prefix
,
const
gchar
*
suffix
,
gpointer
d
)
{
GString
*
str
=
(
GString
*
)
d
;
const
gchar
*
sep
=
""
;
/* don't add fall through tags to the regex */
if
(
!
prefix
||
!
suffix
)
return
;
if
(
str
->
len
>
1
)
sep
=
"|"
;
g_string_append_printf
(
str
,
"%s%s.*?%s"
,
sep
,
prefix
,
suffix
);
}
static
gchar
*
gplate_template_update_pattern
(
GPlateTemplate
*
tplate
)
{
GString
*
str
=
g_string_new
(
"("
);
gchar
*
ret
=
NULL
;
gplate_library_tags_foreach
(
gplate_template_update_pattern_helper
,
str
);
g_string_append_printf
(
str
,
"%s"
,
")"
);
ret
=
str
->
str
;
g_string_free
(
str
,
FALSE
);
return
ret
;
}
typedef
struct
{
const
gchar
*
contents
;
GType
type
;
}
GPlateTemplateFindTagData
;
static
void
gplate_template_find_tag_helper
(
GType
tag
,
const
gchar
*
prefix
,
const
gchar
*
suffix
,
gpointer
d
)
{
GPlateTemplateFindTagData
*
data
=
(
GPlateTemplateFindTagData
*
)
d
;
gchar
*
pattern
=
NULL
;
/* if our tag info doesn't have a prefix or a suffix, we drop out. */
if
(
!
prefix
||
!
suffix
)
return
;
/* create our pattern string */
pattern
=
g_strdup_printf
(
"%s.*?%s"
,
prefix
,
suffix
);
/* look for a match:
*
* G_REGEX_DOTALL is REQUIRED so that newlines get counted.
*
* ie: {{\nfoo\n}} would be treated as a fall through if not for it.
*/
if
(
g_regex_match_simple
(
pattern
,
data
->
contents
,
G_REGEX_DOTALL
,
0
))
data
->
type
=
tag
;
/* cleanup */
g_free
(
pattern
);
}
static
GType
gplate_template_find_tag
(
GPlateTemplate
*
tplate
,
const
gchar
*
contents
)
{
GPlateTemplateFindTagData
d
;
d
.
contents
=
contents
;
d
.
type
=
G_TYPE_INVALID
;
gplate_library_tags_foreach
(
gplate_template_find_tag_helper
,
&
d
);
if
(
d
.
type
==
G_TYPE_INVALID
)
d
.
type
=
gplate_library_get_default_tag
();
return
d
.
type
;
}
static
GList
*
gplate_template_real_tokenize
(
GPlateTemplate
*
tplate
,
const
gchar
*
tplate_string
,
GError
**
error
)
{
GList
*
ret
=
NULL
;
GRegex
*
regex1
=
NULL
;
gchar
**
matches
=
NULL
;
gchar
*
pattern
=
NULL
;
gint
i
=
0
;
pattern
=
gplate_template_update_pattern
(
tplate
);
regex1
=
g_regex_new
(
pattern
,
G_REGEX_OPTIMIZE
,
0
,
error
);
if
(
!
regex1
)
{
g_free
(
pattern
);
return
NULL
;
}
g_free
(
pattern
);
matches
=
g_regex_split
(
regex1
,
tplate_string
,
0
);
for
(
i
=
0
;
matches
[
i
];
i
++
)
{
GPlateTag
*
tag
=
NULL
;
GType
type
=
G_TYPE_INVALID
;
gchar
*
prefix
=
NULL
,
*
suffix
=
NULL
;
if
(
g_utf8_strlen
(
matches
[
i
],
-1
)
<=
0
)
continue
;
type
=
gplate_template_find_tag
(
tplate
,
matches
[
i
]);
if
(
!
gplate_library_lookup_tag
(
type
,
&
prefix
,
&
suffix
,
error
))
continue
;
if
(
!
prefix
&&
!
suffix
)
{
/* it's a fall through tag */
tag
=
g_object_new
(
type
,
"contents"
,
matches
[
i
],
NULL
);
}
else
{
/* it's a normal tag, strip it's prefix and suffix */
GRegex
*
regex2
=
NULL
;
GMatchInfo
*
match
=
NULL
;
gchar
*
pattern
=
NULL
,
*
contents
=
NULL
;
pattern
=
g_strdup_printf
(
"%s(.*?)%s"
,
prefix
,
suffix
);
regex2
=
g_regex_new
(
pattern
,
G_REGEX_OPTIMIZE
|
G_REGEX_DOTALL
,
0
,
error
);
g_free
(
pattern
);
if
(
!
regex2
)
{
GList
*
l
=
NULL
;
for
(
l
=
ret
;
l
;
l
=
l
->
next
)
g_object_unref
(
G_OBJECT
(
l
->
data
));
g_list_free
(
ret
);
return
NULL
;
}
/* get our match info */
if
(
!
g_regex_match
(
regex2
,
matches
[
i
],
0
,
&
match
))
{
GList
*
l
=
NULL
;
g_match_info_free
(
match
);
for
(
l
=
ret
;
l
;
l
=
l
->
next
)
g_object_unref
(
G_OBJECT
(
l
->
data
));
g_list_free
(
ret
);
return
NULL
;
}
contents
=
g_match_info_fetch
(
match
,
1
);
g_strstrip
(
contents
);
g_match_info_free
(
match
);
tag
=
g_object_new
(
type
,
"contents"
,
contents
,
"template"
,
tplate
,
NULL
);
g_free
(
contents
);
}
ret
=
g_list_prepend
(
ret
,
tag
);
}
g_strfreev
(
matches
);
g_regex_unref
(
regex1
);
ret
=
g_list_reverse
(
ret
);
return
ret
;
}
static
GPlateTag
*
gplate_template_real_first_tag
(
GPlateTemplate
*
tplate
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
tplate
);
GPlateTag
*
tag
=
NULL
;
priv
->
current_token
=
priv
->
tokens
;
if
(
priv
->
current_token
&&
GPLATE_IS_TAG
(
priv
->
current_token
->
data
))
tag
=
GPLATE_TAG
(
priv
->
current_token
->
data
);
return
tag
;
}
static
GPlateTag
*
gplate_template_real_last_tag
(
GPlateTemplate
*
tplate
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
tplate
);
GPlateTag
*
tag
=
NULL
;
priv
->
current_token
=
g_list_last
(
priv
->
tokens
);
if
(
priv
->
current_token
&&
GPLATE_IS_TAG
(
priv
->
current_token
->
data
))
tag
=
GPLATE_TAG
(
priv
->
current_token
->
data
);
return
tag
;
}
static
GPlateTag
*
gplate_template_real_current_tag
(
GPlateTemplate
*
tplate
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
tplate
);
GPlateTag
*
tag
=
NULL
;
if
(
priv
->
current_token
&&
GPLATE_IS_TAG
(
priv
->
current_token
->
data
))
tag
=
GPLATE_TAG
(
priv
->
current_token
->
data
);
return
tag
;
}
static
GPlateTag
*
gplate_template_real_next_tag
(
GPlateTemplate
*
tplate
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
tplate
);
GPlateTag
*
tag
=
NULL
;
priv
->
current_token
=
g_list_next
(
priv
->
current_token
);
if
(
priv
->
current_token
&&
GPLATE_IS_TAG
(
priv
->
current_token
->
data
))
tag
=
GPLATE_TAG
(
priv
->
current_token
->
data
);
return
tag
;
}
static
GPlateTag
*
gplate_template_real_previous_tag
(
GPlateTemplate
*
tplate
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
tplate
);
GPlateTag
*
tag
=
NULL
;
priv
->
current_token
=
g_list_previous
(
priv
->
current_token
);
if
(
priv
->
current_token
&&
GPLATE_IS_TAG
(
priv
->
current_token
->
data
))
tag
=
GPLATE_TAG
(
priv
->
current_token
->
data
);
return
tag
;
}
static
GPlateTag
*
gplate_template_real_nth_tag
(
GPlateTemplate
*
tplate
,
guint
nth
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
tplate
);
GPlateTag
*
tag
=
NULL
;
priv
->
current_token
=
g_list_nth
(
priv
->
current_token
,
nth
);
if
(
priv
->
current_token
&&
GPLATE_IS_TAG
(
priv
->
current_token
->
data
))
tag
=
GPLATE_TAG
(
priv
->
current_token
->
data
);
return
tag
;
}
static
GPlateTag
*
gplate_template_real_nth_previous_tag
(
GPlateTemplate
*
tplate
,
guint
nth
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
tplate
);
GPlateTag
*
tag
=
NULL
;
priv
->
current_token
=
g_list_nth_prev
(
priv
->
current_token
,
nth
);
if
(
priv
->
current_token
&&
GPLATE_IS_TAG
(
priv
->
current_token
->
data
))
tag
=
GPLATE_TAG
(
priv
->
current_token
->
data
);
return
tag
;
}
static
void
gplate_template_real_insert_tags
(
GPlateTemplate
*
tplate
,
GList
*
tags
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
tplate
);
/* check if our current node is valid */
if
(
!
priv
->
current_token
)
{
/* check if we have a list of tokens */
if
(
!
priv
->
tokens
)
{
/* no existing tokens, set it to tags and exit */
priv
->
tokens
=
tags
;
}
else
{
/* we have tokens, but we've read the last one, move back to the
* last one.
*/
priv
->
tokens
=
g_list_concat
(
priv
->
tokens
,
tags
);
}
}
else
{
GList
*
tmp
=
NULL
;
/* we have a valid node selected, save it's next node */
tmp
=
priv
->
current_token
->
next
;
/* now mangle current and the first node in tags to shove tags in */
priv
->
current_token
->
next
=
tags
;
tags
->
prev
=
priv
->
current_token
;
/* if the original next node is valid, we need to put them back into
* place
*/
if
(
tmp
)
{
GList
*
last
=
g_list_last
(
tags
);
last
->
next
=
tmp
;
tmp
->
prev
=
last
;
}
}
}
/******************************************************************************
* Object Stuff
*****************************************************************************/
static
void
gplate_template_finalize
(
GObject
*
obj
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
obj
);
GList
*
l
=
NULL
;
g_object_unref
(
priv
->
vars
);
for
(
l
=
priv
->
tokens
;
l
;
l
=
l
->
next
)
g_object_unref
(
G_OBJECT
(
l
->
data
));
g_list_free
(
priv
->
tokens
);
G_OBJECT_CLASS
(
parent_class
)
->
finalize
(
obj
);
}
static
void
gplate_template_class_init
(
GPlateTemplateClass
*
klass
)
{
GObjectClass
*
obj_class
=
G_OBJECT_CLASS
(
klass
);
parent_class
=
g_type_class_peek_parent
(
klass
);
g_type_class_add_private
(
klass
,
sizeof
(
GPlateTemplatePrivate
));
obj_class
->
finalize
=
gplate_template_finalize
;
klass
->
tokenize
=
gplate_template_real_tokenize
;
klass
->
first_tag
=
gplate_template_real_first_tag
;
klass
->
last_tag
=
gplate_template_real_last_tag
;
klass
->
current_tag
=
gplate_template_real_current_tag
;
klass
->
next_tag
=
gplate_template_real_next_tag
;
klass
->
previous_tag
=
gplate_template_real_previous_tag
;
klass
->
nth_tag
=
gplate_template_real_nth_tag
;
klass
->
nth_previous_tag
=
gplate_template_real_nth_previous_tag
;
klass
->
insert_tags
=
gplate_template_real_insert_tags
;
}
static
void
gplate_template_init
(
GTypeInstance
*
self
,
gpointer
klass
)
{
GPlateTemplatePrivate
*
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
self
);
priv
->
vars
=
gplate_dictionary_variable_new
(
"dict"
);
}
/******************************************************************************
* Render helpers
*****************************************************************************/
static
inline
GPlateFunction
*
gplate_template_render_find_function
(
const
gchar
*
name
,
GType
tag
,
gboolean
*
deffunc
,
GError
**
error
)
{
GPlateFunction
*
ret
=
NULL
;
GType
function
=
G_TYPE_INVALID
;
gboolean
def
=
FALSE
;
function
=
gplate_library_lookup_function_for_tag
(
name
,
tag
,
NULL
);
if
(
function
==
G_TYPE_INVALID
)
{
function
=
gplate_library_get_default_function_for_tag
(
tag
,
NULL
);
def
=
TRUE
;
}
if
(
function
!=
G_TYPE_INVALID
)
{
ret
=
g_object_new
(
function
,
NULL
);
if
(
deffunc
)
*
deffunc
=
def
;
}
return
ret
;
}
static
inline
gchar
*
gplate_template_render_token
(
GPlateTemplate
*
tplate
,
const
gchar
*
contents
,
GType
tag
,
GError
**
error
)
{
GPlateFunction
*
function
=
NULL
;
gchar
*
name
=
NULL
,
*
leftovers
=
NULL
,
*
ret
=
NULL
;
gboolean
deffunc
=
FALSE
;
name
=
gplate_util_get_first_word
(
contents
,
&
leftovers
);
if
(
!
name
)
return
g_strdup
(
""
);
function
=
gplate_template_render_find_function
(
name
,
tag
,
&
deffunc
,
error
);
if
(
function
)
{
if
(
deffunc
)
ret
=
gplate_function_evaluate
(
function
,
tplate
,
contents
);
else
ret
=
gplate_function_evaluate
(
function
,
tplate
,
leftovers
);
g_object_unref
(
G_OBJECT
(
function
));
}
g_free
(
name
);
g_free
(
leftovers
);
return
(
ret
)
?
ret
:
g_strdup
(
""
);
}
/******************************************************************************
* GPlateTemplate API
*****************************************************************************/
GType
gplate_template_get_gtype
(
void
)
{
static
GType
type
=
0
;
if
(
type
==
0
)
{
static
const
GTypeInfo
info
=
{
sizeof
(
GPlateTemplateClass
),
NULL
,
NULL
,
(
GClassInitFunc
)
gplate_template_class_init
,
NULL
,
NULL
,
sizeof
(
GPlateTemplate
),
0
,
gplate_template_init
,
};
static
const
GInterfaceInfo
collection_info
=
{
(
GInterfaceInitFunc
)
gplate_template_collection_init
,
NULL
,
NULL
,
};
type
=
g_type_register_static
(
G_TYPE_OBJECT
,
"GPlateTemplate"
,
&
info
,
0
);
g_type_add_interface_static
(
type
,
GPLATE_TYPE_COLLECTION
,
&
collection_info
);
}
return
type
;
}
/**
* gplate_template_new:
*
* Creates a new #GPlateTemplate instance.
*
* Return Value: The new #GPlateTemplate instance.
*/
GPlateTemplate
*
gplate_template_new
(
void
)
{
return
g_object_new
(
GPLATE_TYPE_TEMPLATE
,
NULL
);
}
/**
* gplate_template_tokenize:
* @tplate: The #GPlateTemplate.
* @tplate_string: The string to be translated.
* @error: The return address for any errors.
*
* Tokenizes @tplate_string into a #GList of #GPlateTag's to be later passed to
* #gplate_template_render.
*
* Normally this is called by #gplate_template_render directly, but there are a
* few corner cases where you may want to call this directly.
*
* Return Value: A #GList of #GPlateTags.
*/
GList
*
gplate_template_tokenize
(
GPlateTemplate
*
tplate
,
const
gchar
*
tplate_string
,
GError
**
error
)
{
GPlateTemplateClass
*
klass
=
NULL
;
g_return_val_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
),
NULL
);
g_return_val_if_fail
(
tplate_string
,
NULL
);
klass
=
GPLATE_TEMPLATE_GET_CLASS
(
tplate
);
if
(
klass
&&
klass
->
tokenize
)
return
klass
->
tokenize
(
tplate
,
tplate_string
,
error
);
return
NULL
;
}
/**
* gplate_template_render:
* @tplate: The #GPlateTemplate.
* @tplate_string: The template string to render.
* @error: Return address for errors.
*
* Renders @tplate_string using @tplate.
*
* Return Value: The rendered output.
*/
gchar
*
gplate_template_render
(
GPlateTemplate
*
tplate
,
const
gchar
*
tplate_string
,
GError
**
error
)
{
GPlateTemplatePrivate
*
priv
=
NULL
;
GPlateTag
*
tag
=
NULL
;
GString
*
str
=
NULL
;
gchar
*
ret
=
NULL
;
g_return_val_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
),
NULL
);
g_return_val_if_fail
(
tplate_string
,
NULL
);
priv
=
GPLATE_TEMPLATE_GET_PRIVATE
(
tplate
);
priv
->
tokens
=
gplate_template_tokenize
(
tplate
,
tplate_string
,
error
);
if
(
!
priv
->
tokens
)
return
g_strdup
(
""
);
/* for whatever reason, using g_string_new_len here doesn't work */
str
=
g_string_new
(
""
);
for
(
tag
=
gplate_template_first_tag
(
tplate
);
tag
;
tag
=
gplate_template_next_tag
(
tplate
))
{
GType
ttype
=
G_OBJECT_TYPE
(
tag
);
gchar
*
contents
=
NULL
,
*
output
=
NULL
;
contents
=
gplate_tag_get_contents
(
tag
);
output
=
gplate_template_render_token
(
tplate
,
contents
,
ttype
,
error
);
g_string_append_printf
(
str
,
"%s"
,
output
);
g_free
(
contents
);
g_free
(
output
);
}
ret
=
str
->
str
;
g_string_free
(
str
,
FALSE
);
return
ret
;
}
/**
* gplate_template_render_file:
* @tplate: The #GPlateTemplate.
* @filename: The file name to render.
* @error: Return address for errors.
*
* Renders @filename using #GPlateTemplate @tplate.
*
* Return Value: The rendered output.
*/
gchar
*
gplate_template_render_file
(
GPlateTemplate
*
tplate
,
const
gchar
*
filename
,
GError
**
error
)
{
gchar
*
contents
=
NULL
,
*
ret
=
NULL
;
g_return_val_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
),
NULL
);
g_return_val_if_fail
(
filename
,
NULL
);
if
(
!
gplate_util_read_file
(
filename
,
&
contents
,
NULL
,
error
))
return
FALSE
;
ret
=
gplate_template_render
(
tplate
,
contents
,
error
);
g_free
(
contents
);
return
ret
;
}
/**
* gplate_template_first_tag:
* @tplate: The #GPlateTemplate.
*
* Moves the tag stack to the first tag and returns it.
*
* Return Value: The first tag or NULL.
*/
GPlateTag
*
gplate_template_first_tag
(
GPlateTemplate
*
tplate
)
{
GPlateTemplateClass
*
klass
=
NULL
;
g_return_val_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
),
NULL
);
klass
=
GPLATE_TEMPLATE_GET_CLASS
(
tplate
);
if
(
klass
&&
klass
->
first_tag
)
return
klass
->
first_tag
(
tplate
);
return
NULL
;
}
/**
* gplate_template_last_tag:
* @tplate: The #GPlateTemplate.
*
* Moves the tag stack to the last tag and returns it.
*
* Return Value: The last tag or NULL.
*/
GPlateTag
*
gplate_template_last_tag
(
GPlateTemplate
*
tplate
)
{
GPlateTemplateClass
*
klass
=
NULL
;
g_return_val_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
),
NULL
);
klass
=
GPLATE_TEMPLATE_GET_CLASS
(
tplate
);
if
(
klass
&&
klass
->
last_tag
)
return
klass
->
last_tag
(
tplate
);
return
NULL
;
}
/**
* gplate_template_current_tag:
* @tplate: The #GPlateTemplate.
*
* Returns the current tag.
*
* Return Value: The current tag or NULL.
*/
GPlateTag
*
gplate_template_current_tag
(
GPlateTemplate
*
tplate
)
{
GPlateTemplateClass
*
klass
=
NULL
;
g_return_val_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
),
NULL
);
klass
=
GPLATE_TEMPLATE_GET_CLASS
(
tplate
);
if
(
klass
&&
klass
->
current_tag
)
return
klass
->
current_tag
(
tplate
);
return
NULL
;
}
/**
* gplate_template_next_tag:
* @tplate: The #GPlateTemplate.
*
* Moves the tag stack forward one tag and returns it.
*
* Return Value: The previous tag or NULL.
*/
GPlateTag
*
gplate_template_next_tag
(
GPlateTemplate
*
tplate
)
{
GPlateTemplateClass
*
klass
=
NULL
;
g_return_val_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
),
NULL
);
klass
=
GPLATE_TEMPLATE_GET_CLASS
(
tplate
);
if
(
klass
&&
klass
->
next_tag
)
return
klass
->
next_tag
(
tplate
);
return
NULL
;
}
/**
* gplate_template_previous_tag:
* @tplate: The #GPlateTemplate.
*
* Moves the tag stack back one tag and returns it.
*
* Return Value: The previous tag or NULL.
*/
GPlateTag
*
gplate_template_previous_tag
(
GPlateTemplate
*
tplate
)
{
GPlateTemplateClass
*
klass
=
NULL
;
g_return_val_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
),
NULL
);
klass
=
GPLATE_TEMPLATE_GET_CLASS
(
tplate
);
if
(
klass
&&
klass
->
previous_tag
)
return
klass
->
previous_tag
(
tplate
);
return
NULL
;
}
/**
* gplate_template_nth_tag:
* @tplate: The #GPlateTemplate.
* @nth: The number of tags to move forwards.
*
* Moves the tag stack forward @nth tags and returns that tag.
*
* Return Value: The @nth tag or NULL.
*/
GPlateTag
*
gplate_template_nth_tag
(
GPlateTemplate
*
tplate
,
guint
nth
)
{
GPlateTemplateClass
*
klass
=
NULL
;
g_return_val_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
),
NULL
);
klass
=
GPLATE_TEMPLATE_GET_CLASS
(
tplate
);
if
(
klass
&&
klass
->
nth_tag
)
return
klass
->
nth_tag
(
tplate
,
nth
);
return
NULL
;
}
/**
* gplate_template_nth_previous_tag:
* @tplate: The #GPlateTemplate.
* @nth: The number of tags to move backwards.
*
* Moves the tag stack back @nth tags and returns that tag.
*
* Return Value: The @nth previous tag or NULL.
*/
GPlateTag
*
gplate_template_nth_previous_tag
(
GPlateTemplate
*
tplate
,
guint
nth
)
{
GPlateTemplateClass
*
klass
=
NULL
;
g_return_val_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
),
NULL
);
klass
=
GPLATE_TEMPLATE_GET_CLASS
(
tplate
);
if
(
klass
&&
klass
->
nth_previous_tag
)
return
klass
->
nth_previous_tag
(
tplate
,
nth
);
return
NULL
;
}
/**
* gplate_template_insert_tags:
* @tplate: The #GPlateTemplate.
* @tags: A #GList of #GPlateTag's to insert.
*
* Inserts @tags after the current tag in @tplate's stack.
*/
void
gplate_template_insert_tags
(
GPlateTemplate
*
tplate
,
GList
*
tags
)
{
GPlateTemplateClass
*
klass
=
NULL
;
g_return_if_fail
(
GPLATE_IS_TEMPLATE
(
tplate
));
g_return_if_fail
(
tags
);
klass
=
GPLATE_TEMPLATE_GET_CLASS
(
tplate
);
if
(
klass
&&
klass
->
insert_tags
)
klass
->
insert_tags
(
tplate
,
tags
);
}