]> git.sur5r.net Git - glabels/blob - glabels2/src/text-node.c
Initial revision
[glabels] / glabels2 / src / text-node.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  text_node.c:  text node module
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22
23 #include <config.h>
24
25 #include "text-node.h"
26
27 #include "merge.h"
28
29 #include "debug.h"
30
31 /*===========================================*/
32 /* Local function prototypes                 */
33 /*===========================================*/
34
35 static glTextNode *extract_text_node (gchar * text, gint * n);
36
37 \f
38 /*--------------------------------------------------------------------------*/
39 /* Expand single node into representative string.                           */
40 /*--------------------------------------------------------------------------*/
41 gchar *
42 gl_text_node_expand (glTextNode * text_node,
43                      glMergeRecord * record)
44 {
45         gchar *text;
46
47         if (text_node->field_flag) {
48                 text = gl_merge_eval_key (text_node->data, record);
49                 if (text != NULL) {
50                         return text;
51                 } else {
52                         return g_strdup_printf ("FIELD{%s}", text_node->data);
53                 }
54         } else {
55                 return g_strdup (text_node->data);
56         }
57 }
58
59 /*--------------------------------------------------------------------------*/
60 /* Create a single text node from given text.                               */
61 /*--------------------------------------------------------------------------*/
62 glTextNode *
63 gl_text_node_new_from_text (gchar * text)
64 {
65         gint n;
66
67         return extract_text_node (text, &n);
68 }
69
70 /*--------------------------------------------------------------------------*/
71 /* PRIVATE.  Create a single text node from given text. n = characters used */
72 /*--------------------------------------------------------------------------*/
73 static glTextNode *
74 extract_text_node (gchar * text,
75                    gint * n)
76 {
77         glTextNode *text_node;
78         gchar *p;
79         gint m;
80
81         text_node = g_new0 (glTextNode, 1);
82
83         if (strncmp (text, "FIELD{", strlen ("FIELD{")) == 0) {
84                 /* We are at the beginning of a "FIELD" node */
85                 text_node->field_flag = TRUE;
86                 *n = strlen ("FIELD{");
87                 text += *n;
88                 for (p = text, m = 0; *p != 0; p++, m++, (*n)++) {
89                         if (*p == '}') {
90                                 (*n)++;
91                                 break;
92                         }
93                 }
94                 text_node->data = g_strndup (text, m);
95         } else {
96                 /* We are at the beginning of a literal node */
97                 text_node->field_flag = FALSE;
98                 for (p = text, *n = 0; *p != 0; p++, (*n)++) {
99                         if (strncmp (p, "FIELD{", strlen ("FIELD{")) == 0)
100                                 break;
101                         if (*p == '\n')
102                                 break;
103                 }
104                 text_node->data = g_strndup (text, *n);
105         }
106
107         return text_node;
108 }
109
110 /*--------------------------------------------------------------------------*/
111 /* Copy a single text node.                                                 */
112 /*--------------------------------------------------------------------------*/
113 glTextNode *
114 gl_text_node_dup (glTextNode *src)
115 {
116         glTextNode *dst;
117
118         dst = g_new0 (glTextNode, 1);
119
120         dst->field_flag = src->field_flag;
121         dst->data = g_strdup (src->data);
122
123         return dst;
124 }
125
126 /*--------------------------------------------------------------------------*/
127 /* Free a single text node.                                                 */
128 /*--------------------------------------------------------------------------*/
129 void
130 gl_text_node_free (glTextNode ** text_node)
131 {
132         if ( *text_node == NULL ) return;
133
134         g_free ((*text_node)->data);
135         (*text_node)->data = NULL;
136         g_free (*text_node);
137         *text_node = NULL;
138 }
139
140 /*--------------------------------------------------------------------------*/
141 /* Expand text lines into single string.                                    */
142 /*--------------------------------------------------------------------------*/
143 gchar *
144 gl_text_node_lines_expand (GList * lines,
145                            glMergeRecord * record)
146 {
147         GList *p_line, *p_node;
148         glTextNode *text_node;
149         gchar *text, *old_text, *expanded_node;
150
151         text = g_strdup ("");   /* prime pointer for concatenation */
152         for (p_line = lines; p_line != NULL; p_line = p_line->next) {
153                 for (p_node = (GList *) p_line->data; p_node != NULL;
154                      p_node = p_node->next) {
155                         text_node = (glTextNode *) p_node->data;
156                         old_text = text;
157                         expanded_node = gl_text_node_expand (text_node, record);
158                         text = g_strconcat (text, expanded_node, NULL);
159                         g_free (old_text);
160                         g_free (expanded_node);
161                 }
162                 if ( p_line->next != NULL ) {
163                         old_text = text;
164                         text = g_strconcat (text, "\n", NULL);
165                         g_free (old_text);
166                 }
167         }
168
169         return text;
170 }
171
172 /*--------------------------------------------------------------------------*/
173 /* Parse a string back into text lines.                                     */
174 /*--------------------------------------------------------------------------*/
175 GList *
176 gl_text_node_lines_new_from_text (gchar * text)
177 {
178         GList *lines, *nodes;
179         glTextNode *text_node;
180         gchar *p;
181         gint n;
182
183         lines = NULL;
184         nodes = NULL;
185         for (p = text; *p != 0; p += n) {
186                 if (*p != '\n') {
187                         text_node = extract_text_node (p, &n);
188                         nodes = g_list_append (nodes, text_node);
189                 } else {
190                         n = 1;
191                         lines = g_list_append (lines, nodes);
192                         nodes = NULL;
193                 }
194         }
195         if (*(p - 1) != '\n') {
196                 lines = g_list_append (lines, nodes);
197         }
198
199         return lines;
200 }
201
202 /*--------------------------------------------------------------------------*/
203 /* Copy a list of text lines.                                               */
204 /*--------------------------------------------------------------------------*/
205 GList *
206 gl_text_node_lines_dup (GList * src_lines)
207 {
208         GList *dst_lines=NULL;
209         GList *p_line, *line, *p_node;
210         glTextNode *node;
211
212         for (p_line = src_lines; p_line != NULL; p_line = p_line->next) {
213                 line = NULL;
214                 for (p_node = (GList *) p_line->data; p_node != NULL;
215                      p_node = p_node->next) {
216                         node = gl_text_node_dup ((glTextNode *)p_node->data);
217                         line = g_list_append (line, node);
218                 }
219                 dst_lines = g_list_append (dst_lines, line);
220         }
221
222         return dst_lines;
223 }
224
225 /*--------------------------------------------------------------------------*/
226 /* Free a list of text lines.                                               */
227 /*--------------------------------------------------------------------------*/
228 void
229 gl_text_node_lines_free (GList ** lines)
230 {
231         GList *p_line, *p_node;
232
233         for (p_line = *lines; p_line != NULL; p_line = p_line->next) {
234                 for (p_node = (GList *) p_line->data; p_node != NULL;
235                      p_node = p_node->next) {
236                         gl_text_node_free ( (glTextNode **) &(p_node->data) );
237                 }
238                 g_list_free ((GList *) p_line->data);
239                 p_line->data = NULL;
240         }
241
242         g_list_free (*lines);
243         *lines = NULL;
244 }
245
246 /****************************************************************************/
247 /* For debugging:  descend and print lines list.                            */
248 /****************************************************************************/
249 void
250 gl_text_node_lines_print (GList * lines )
251 {
252         GList *p_line, *p_node;
253         glTextNode *text_node;
254         gint i_line, i_node;
255
256         for (p_line=lines, i_line=0; p_line != NULL; p_line=p_line->next, i_line++) {
257                 for (p_node = (GList *) p_line->data, i_node=0; p_node != NULL;
258                      p_node = p_node->next, i_node++) {
259                         text_node = (glTextNode *) p_node->data;
260                         g_print( "LINE[%d], NODE[%d] = { %d, \"%s\" }\n",
261                                  i_line, i_node,
262                                  text_node->field_flag, text_node->data );
263
264                 }
265         }
266
267 }
268