1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * text_node.c: text node module
8 * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "text-node.h"
35 /*===========================================*/
36 /* Local function prototypes */
37 /*===========================================*/
39 static glTextNode *extract_text_node (gchar *text,
42 static gboolean is_empty_field (glTextNode *text_node,
43 glMergeRecord *record);
46 /****************************************************************************/
47 /* Expand single node into representative string. */
48 /****************************************************************************/
50 gl_text_node_expand (glTextNode *text_node,
51 glMergeRecord *record)
55 if (text_node->field_flag) {
57 return g_strdup_printf ("${%s}", text_node->data);
59 text = gl_merge_eval_key (record, text_node->data);
63 return g_strdup_printf ("%s", "");
67 return g_strdup (text_node->data);
71 /*--------------------------------------------------------------------------*/
72 /* PRIVATE. Is node a field that evaluates empty? */
73 /*--------------------------------------------------------------------------*/
75 is_empty_field (glTextNode *text_node,
76 glMergeRecord *record)
81 if ( (record != NULL) && text_node->field_flag) {
82 text = gl_merge_eval_key (record, text_node->data);
83 if ( (text == NULL) || (text[0] == 0) ) {
92 /****************************************************************************/
93 /* Create a single text node from given text. */
94 /****************************************************************************/
96 gl_text_node_new_from_text (gchar *text)
100 return extract_text_node (text, &n);
103 /*--------------------------------------------------------------------------*/
104 /* PRIVATE. Create a single text node from given text. n = characters used */
105 /*--------------------------------------------------------------------------*/
107 extract_text_node (gchar *text,
110 glTextNode *text_node;
114 text_node = g_new0 (glTextNode, 1);
116 if (strncmp (text, "${", strlen ("${")) == 0) {
117 /* We are at the beginning of a "FIELD" node */
118 text_node->field_flag = TRUE;
121 for (p = text, m = 0; *p != 0; p++, m++, (*n)++) {
127 text_node->data = g_strndup (text, m);
129 /* We are at the beginning of a literal node */
130 text_node->field_flag = FALSE;
131 for (p = text, *n = 0; *p != 0; p++, (*n)++) {
132 if (strncmp (p, "${", strlen ("${")) == 0)
137 text_node->data = g_strndup (text, *n);
143 /****************************************************************************/
144 /* Copy a single text node. */
145 /****************************************************************************/
147 gl_text_node_dup (glTextNode *src)
151 if ( src == NULL ) return NULL;
153 dst = g_new0 (glTextNode, 1);
155 dst->field_flag = src->field_flag;
156 dst->data = g_strdup (src->data);
161 /****************************************************************************/
162 /* Free a single text node. */
163 /****************************************************************************/
165 gl_text_node_free (glTextNode **text_node)
167 if ( *text_node == NULL ) return;
169 g_free ((*text_node)->data);
170 (*text_node)->data = NULL;
175 /****************************************************************************/
176 /* Compare 2 text nodes for equality. */
177 /****************************************************************************/
179 gl_text_node_equal (glTextNode *text_node1,
180 glTextNode *text_node2)
182 /* First take care of the case of either or both being NULL. */
183 if ( text_node1 == NULL ) {
184 return ( text_node2 == NULL );
186 if ( text_node2 == NULL ) {
191 /* Bail if field flags differ. */
192 if ( text_node1->field_flag != text_node2->field_flag ) {
196 /* Now take care of the case of either or both data fields being NULL. */
197 if ( text_node1->data == NULL ) {
198 return ( text_node2->data == NULL );
200 if ( text_node2->data == NULL ) {
205 /* Field flags are identical, so now compare the data. */
206 return (strcmp (text_node1->data, text_node2->data) == 0);
209 /****************************************************************************/
210 /* Expand text lines into single string. */
211 /****************************************************************************/
213 gl_text_node_lines_expand (GList *lines,
214 glMergeRecord *record)
216 GList *p_line, *p_node;
217 glTextNode *text_node;
218 gchar *text, *old_text, *expanded_node;
220 text = g_strdup (""); /* prime pointer for concatenation */
221 for (p_line = lines; p_line != NULL; p_line = p_line->next) {
223 /* special case: something like ${ADDRESS2} = "" on line by itself. */
224 /* in such circumstances ignore the line completely. */
225 p_node = (GList *)p_line->data;
226 if (p_node && p_node->next == NULL) {
227 text_node = (glTextNode *) p_node->data;
228 if ( is_empty_field (text_node, record) ) {
233 /* expand each node */
234 for (p_node = (GList *) p_line->data; p_node != NULL;
235 p_node = p_node->next) {
236 text_node = (glTextNode *) p_node->data;
238 expanded_node = gl_text_node_expand (text_node, record);
239 text = g_strconcat (text, expanded_node, NULL);
241 g_free (expanded_node);
244 /* append newline to each line, except last. */
245 if ( p_line->next != NULL ) {
247 text = g_strconcat (text, "\n", NULL);
255 /****************************************************************************/
256 /* Parse a string back into text lines. */
257 /****************************************************************************/
259 gl_text_node_lines_new_from_text (gchar *text)
261 GList *lines, *nodes;
262 glTextNode *text_node;
268 for (p = text; *p != 0; p += n) {
270 text_node = extract_text_node (p, &n);
271 nodes = g_list_append (nodes, text_node);
274 lines = g_list_append (lines, nodes);
278 if (*(p - 1) != '\n') {
279 lines = g_list_append (lines, nodes);
285 /****************************************************************************/
286 /* Copy a list of text lines. */
287 /****************************************************************************/
289 gl_text_node_lines_dup (GList *src_lines)
291 GList *dst_lines=NULL;
292 GList *p_line, *line, *p_node;
295 for (p_line = src_lines; p_line != NULL; p_line = p_line->next)
298 for (p_node = (GList *) p_line->data; p_node != NULL; p_node = p_node->next)
300 node = gl_text_node_dup ((glTextNode *)p_node->data);
301 line = g_list_append (line, node);
303 dst_lines = g_list_append (dst_lines, line);
309 /****************************************************************************/
310 /* Free a list of text lines. */
311 /****************************************************************************/
313 gl_text_node_lines_free (GList **lines)
315 GList *p_line, *p_node;
316 glTextNode *text_node;
318 for (p_line = *lines; p_line != NULL; p_line = p_line->next)
320 for (p_node = (GList *) p_line->data; p_node != NULL; p_node = p_node->next)
322 text_node = (glTextNode *)p_node->data;
324 gl_text_node_free ( &text_node );
326 g_list_free ((GList *) p_line->data);
330 g_list_free (*lines);
334 /****************************************************************************/
335 /* For debugging: descend and print lines list. */
336 /****************************************************************************/
338 gl_text_node_lines_print (GList * lines )
340 GList *p_line, *p_node;
341 glTextNode *text_node;
344 for (p_line=lines, i_line=0; p_line != NULL; p_line=p_line->next, i_line++) {
345 for (p_node = (GList *) p_line->data, i_node=0; p_node != NULL;
346 p_node = p_node->next, i_node++) {
347 text_node = (glTextNode *) p_node->data;
348 g_print( "LINE[%d], NODE[%d] = { %d, \"%s\" }\n",
350 text_node->field_flag, text_node->data );