]> git.sur5r.net Git - glabels/blob - glabels2/src/merge.c
Initial revision
[glabels] / glabels2 / src / merge.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  merge.c:  document merge module
5  *
6  *  Copyright (C) 2001  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 <gnome.h>
26
27 #include "merge.h"
28 #include "merge-text.h"
29
30 #include "debug.h"
31
32 /*===========================================*/
33 /* Private types                             */
34 /*===========================================*/
35 typedef struct {
36         gchar *short_text;
37         gchar *long_text;
38 } TypeTexts;
39
40 typedef struct {
41
42         glMergeInput * (*open) (glMergeType, GList *, gchar *);
43         void (*close) (glMergeInput *);
44         glMergeRecord * (*get_record) (glMergeInput *);
45         GList * (*get_raw_record) (glMergeInput *);
46
47 } BackendFunctions;
48
49 /*===========================================*/
50 /* Private globals                           */
51 /*===========================================*/
52
53 static TypeTexts type_text[GL_MERGE_N_TYPES];
54
55 static BackendFunctions func[GL_MERGE_N_TYPES];
56
57 /*===========================================*/
58 /* Local function prototypes                 */
59 /*===========================================*/
60
61 \f
62 /*****************************************************************************/
63 /* Initialize module.                                                        */
64 /*****************************************************************************/
65 void
66 gl_merge_init (void)
67 {
68         gint i;
69
70         gl_debug (DEBUG_MERGE, "START");
71
72         /* Register backend functions and data. */
73
74         i = GL_MERGE_NONE;
75         func[i].open = NULL;
76         func[i].close = NULL;
77         func[i].get_record = NULL;
78         func[i].get_raw_record = NULL;
79         type_text[i].short_text = "None";
80         type_text[i].long_text = _("None");
81
82         i = GL_MERGE_TEXT_TAB;
83         func[i].open = gl_merge_text_open;
84         func[i].close = gl_merge_text_close;
85         func[i].get_record = gl_merge_text_get_record;
86         func[i].get_raw_record = gl_merge_text_get_raw_record;
87         type_text[i].short_text = "Text/Tab";
88         type_text[i].long_text = _("Text with tab separators");
89
90         i = GL_MERGE_TEXT_COMMA;
91         func[i].open = gl_merge_text_open;
92         func[i].close = gl_merge_text_close;
93         func[i].get_record = gl_merge_text_get_record;
94         func[i].get_raw_record = gl_merge_text_get_raw_record;
95         type_text[i].short_text = "Text/Comma";
96         type_text[i].long_text = _("Text with comma separators");
97
98         i = GL_MERGE_TEXT_COLON;
99         func[i].open = gl_merge_text_open;
100         func[i].close = gl_merge_text_close;
101         func[i].get_record = gl_merge_text_get_record;
102         func[i].get_raw_record = gl_merge_text_get_raw_record;
103         type_text[i].short_text = "Text/Colon";
104         type_text[i].long_text = _("Text with colon separators");
105
106         gl_debug (DEBUG_MERGE, "END");
107 }
108
109 /*****************************************************************************/
110 /* Create new merge information structure.                                   */
111 /*****************************************************************************/
112 glMerge *gl_merge_new (void)
113 {
114         gl_debug (DEBUG_MERGE, "");
115
116         return g_new0 (glMerge, 1);
117 }
118
119 /*****************************************************************************/
120 /* Duplicate merge information structure.                                    */
121 /*****************************************************************************/
122 glMerge *gl_merge_dup (glMerge *orig)
123 {
124         glMerge *new;
125
126         gl_debug (DEBUG_MERGE, "START");
127
128         new = gl_merge_new ();
129
130         new->type       = orig->type;
131         new->src        = g_strdup (orig->src);
132         new->field_defs = gl_merge_dup_field_def_list (orig->field_defs);
133
134         gl_debug (DEBUG_MERGE, "END");
135         return new;
136 }
137
138 /*****************************************************************************/
139 /* Free existing merge information structure.                                */
140 /*****************************************************************************/
141 void    gl_merge_free (glMerge **merge)
142 {
143         gl_debug (DEBUG_MERGE, "START");
144
145         g_free ((*merge)->src);
146         (*merge)->src = NULL;
147         gl_merge_free_field_def_list (&(*merge)->field_defs);
148
149         *merge = NULL;
150
151         gl_debug (DEBUG_MERGE, "END");
152 }
153
154 /*****************************************************************************/
155 /* Lookup type from short text.                                              */
156 /*****************************************************************************/
157 glMergeType
158 gl_merge_text_to_type (gchar * text)
159 {
160         glMergeType type;
161
162         gl_debug (DEBUG_MERGE, "START");
163
164         for (type = 0; type < GL_MERGE_N_TYPES; type++) {
165                 if (g_strcasecmp (text, type_text[type].short_text) == 0) {
166                         gl_debug (DEBUG_MERGE, "END");
167                         return type;
168                 }
169         }
170
171         gl_debug (DEBUG_MERGE, "END");
172
173         return GL_MERGE_NONE;
174 }
175
176 /*****************************************************************************/
177 /* Lookup short text for given type.                                         */
178 /*****************************************************************************/
179 gchar *
180 gl_merge_type_to_text (glMergeType type)
181 {
182         gl_debug (DEBUG_MERGE, "");
183
184         return g_strdup (type_text[type].short_text);
185 }
186
187 /*****************************************************************************/
188 /* Lookup type from long descriptive text.                                   */
189 /*****************************************************************************/
190 glMergeType
191 gl_merge_long_text_to_type (gchar * text)
192 {
193         glMergeType type;
194
195         gl_debug (DEBUG_MERGE, "START");
196
197         for (type = 0; type < GL_MERGE_N_TYPES; type++) {
198                 if (g_strcasecmp (text, type_text[type].long_text) == 0) {
199                         gl_debug (DEBUG_MERGE, "END");
200                         return type;
201                 }
202         }
203
204         gl_debug (DEBUG_MERGE, "END");
205         return GL_MERGE_NONE;
206 }
207
208 /*****************************************************************************/
209 /* Lookup longer, more descriptive text for given type.                      */
210 /*****************************************************************************/
211 gchar *
212 gl_merge_type_to_long_text (glMergeType type)
213 {
214         gl_debug (DEBUG_MERGE, "");
215
216         return g_strdup (type_text[type].long_text);
217 }
218
219 /*****************************************************************************/
220 /* Retrieve a list of descriptive texts for all available types.             */
221 /*****************************************************************************/
222 GList *
223 gl_merge_get_long_texts_list (void)
224 {
225         glMergeType type;
226         GList *list = NULL;
227
228         gl_debug (DEBUG_MERGE, "START");
229
230         for (type = 0; type < GL_MERGE_N_TYPES; type++) {
231
232                 list = g_list_append (list, gl_merge_type_to_long_text (type));
233
234         }
235
236         gl_debug (DEBUG_MERGE, "END");
237         return list;
238 }
239
240 /*****************************************************************************/
241 /* Free list of descriptive texts.                                           */
242 /*****************************************************************************/
243 void
244 gl_merge_free_long_texts_list (GList ** list)
245 {
246         GList *p;
247
248         gl_debug (DEBUG_MERGE, "START");
249
250         for (p = *list; p != NULL; p = p->next) {
251                 g_free (p->data);
252                 p->data = NULL;
253         }
254
255         g_list_free (*list);
256         *list = NULL;
257
258         gl_debug (DEBUG_MERGE, "END");
259 }
260
261 /*****************************************************************************/
262 /* Duplicate field definitions.                                              */
263 /*****************************************************************************/
264 GList *gl_merge_dup_field_def_list (GList * orig)
265 {
266         GList *new, *p_orig;
267         glMergeFieldDefinition *fd_new, *fd_orig;
268
269         gl_debug (DEBUG_MERGE, "START");
270
271         new = NULL;
272         for (p_orig = orig; p_orig != NULL; p_orig = p_orig->next) {
273                 fd_orig = (glMergeFieldDefinition *) p_orig->data;
274                 fd_new  = g_new0 (glMergeFieldDefinition, 1);
275
276                 fd_new->key = g_strdup (fd_orig->key);
277                 fd_new->loc = g_strdup (fd_orig->loc);
278
279                 new = g_list_append (new, fd_new);
280         }
281
282         gl_debug (DEBUG_MERGE, "END");
283         return new;
284 }
285
286 /*****************************************************************************/
287 /* Free list of field definitions.                                           */
288 /*****************************************************************************/
289 void
290 gl_merge_free_field_def_list (GList ** list)
291 {
292         GList *p;
293         glMergeFieldDefinition *field_def;
294
295         gl_debug (DEBUG_MERGE, "START");
296
297         for (p = *list; p != NULL; p = p->next) {
298                 field_def = (glMergeFieldDefinition *) p->data;
299
300                 g_free (field_def->key);
301                 field_def->key = NULL;
302                 g_free (field_def->loc);
303                 field_def->loc = NULL;
304
305                 g_free (p->data);
306                 p->data = NULL;
307         }
308
309         g_list_free (*list);
310         *list = NULL;
311
312         gl_debug (DEBUG_MERGE, "END");
313 }
314
315 /*****************************************************************************/
316 /* Extract a list of valid keys from field definitions list                  */
317 /*****************************************************************************/
318 GList *
319 gl_merge_get_key_list (GList * field_defs)
320 {
321         GList *p, *keys;
322         glMergeFieldDefinition *field_def;
323
324         gl_debug (DEBUG_MERGE, "START");
325
326         keys = NULL;
327         for (p = field_defs; p != NULL; p = p->next) {
328                 field_def = (glMergeFieldDefinition *) p->data;
329
330                 keys = g_list_append (keys, g_strdup (field_def->key));
331         }
332
333         gl_debug (DEBUG_MERGE, "END");
334
335         return keys;
336 }
337
338 /*****************************************************************************/
339 /* Free a list of keys.                                                      */
340 /*****************************************************************************/
341 void
342 gl_merge_free_key_list (GList ** keys)
343 {
344         GList *p;
345
346         gl_debug (DEBUG_MERGE, "START");
347
348         for (p = *keys; p != NULL; p = p->next) {
349                 g_free (p->data);
350                 p->data = NULL;
351         }
352
353         g_list_free (*keys);
354         *keys = NULL;
355
356         gl_debug (DEBUG_MERGE, "END");
357 }
358
359 /*****************************************************************************/
360 /* Lookup key for given locator.                                             */
361 /*****************************************************************************/
362 gchar *
363 gl_merge_find_key (GList * field_defs,
364                    gchar * loc)
365 {
366         GList *p;
367         glMergeFieldDefinition *field_def;
368
369         gl_debug (DEBUG_MERGE, "START");
370
371         for (p = field_defs; p != NULL; p = p->next) {
372                 field_def = (glMergeFieldDefinition *) p->data;
373
374                 if (strcmp (loc, field_def->loc) == 0) {
375                         gl_debug (DEBUG_MERGE, "END");
376                         return g_strdup (field_def->key);
377                 }
378
379         }
380
381         gl_debug (DEBUG_MERGE, "END");
382
383         return NULL;
384 }
385
386 /*****************************************************************************/
387 /* Open merge source front-end.                                              */
388 /*****************************************************************************/
389 glMergeInput *
390 gl_merge_open (glMergeType type,
391                GList * field_defs,
392                gchar * src)
393 {
394         gl_debug (DEBUG_MERGE, "");
395
396         return func[type].open (type, field_defs, src);
397 }
398
399 /*****************************************************************************/
400 /* Close merge source front-end.                                             */
401 /*****************************************************************************/
402 void
403 gl_merge_close (glMergeInput * input)
404 {
405         gl_debug (DEBUG_MERGE, "START");
406
407         if ( input != NULL ) {
408                 func[input->type].close (input);
409         }
410
411         gl_debug (DEBUG_MERGE, "END");
412 }
413
414 /*****************************************************************************/
415 /* Get next record from merge source, NULL if exhausted (front-end).         */
416 /*****************************************************************************/
417 glMergeRecord *
418 gl_merge_get_record (glMergeInput * input)
419 {
420         gl_debug (DEBUG_MERGE, "");
421
422         if ( input == NULL ) {
423                 return NULL;
424         }
425         return func[input->type].get_record (input);
426 }
427
428 /*****************************************************************************/
429 /* Get next record (raw) from merge source, NULL if exhausted (front-end).   */
430 /*****************************************************************************/
431 GList *
432 gl_merge_get_raw_record (glMergeInput * input)
433 {
434         gl_debug (DEBUG_MERGE, "");
435
436         if ( input == NULL ) {
437                 return NULL;
438         }
439         return func[input->type].get_raw_record (input);
440 }
441
442 /*****************************************************************************/
443 /* Free a merge record (list of fields)                                      */
444 /*****************************************************************************/
445 void
446 gl_merge_free_record (glMergeRecord ** record)
447 {
448         GList *p;
449         glMergeField *field;
450
451         gl_debug (DEBUG_MERGE, "START");
452
453         for (p = (*record)->field_list; p != NULL; p = p->next) {
454                 field = (glMergeField *) p->data;
455
456                 g_free (field->key);
457                 field->key = NULL;
458                 g_free (field->value);
459                 field->value = NULL;
460
461                 g_free (p->data);
462                 p->data = NULL;
463
464         }
465         g_list_free ((*record)->field_list);
466         (*record)->field_list = NULL;
467
468         g_free (*record);
469         *record = NULL;
470
471         gl_debug (DEBUG_MERGE, "END");
472 }
473
474 /*****************************************************************************/
475 /* Free a merge record (list of fields)                                      */
476 /*****************************************************************************/
477 void
478 gl_merge_free_raw_record (GList ** record)
479 {
480         GList *p;
481         glMergeRawField *field;
482
483         gl_debug (DEBUG_MERGE, "START");
484
485         for (p = *record; p != NULL; p = p->next) {
486                 field = (glMergeRawField *) p->data;
487
488                 g_free (field->loc);
489                 field->loc = NULL;
490                 g_free (field->value);
491                 field->value = NULL;
492
493                 g_free (p->data);
494                 p->data = NULL;
495
496         }
497
498         g_list_free (*record);
499         *record = NULL;
500
501         gl_debug (DEBUG_MERGE, "END");
502 }
503
504 /*****************************************************************************/
505 /* Find key in given record and evaluate.                                    */
506 /*****************************************************************************/
507 extern gchar *
508 gl_merge_eval_key (gchar * key,
509                    glMergeRecord * record)
510 {
511         GList *p;
512         glMergeField *field;
513
514         gl_debug (DEBUG_MERGE, "START");
515
516         if ( record != NULL ) {
517                 for (p = record->field_list; p != NULL; p = p->next) {
518                         field = (glMergeField *) p->data;
519
520                         if (strcmp (key, field->key) == 0) {
521                                 gl_debug (DEBUG_MERGE, "END");
522                                 return g_strdup (field->value);
523                         }
524
525                 }
526         }
527
528         gl_debug (DEBUG_MERGE, "END");
529
530         return NULL;
531 }
532
533 /*****************************************************************************/
534 /* Read all records from merge source.                                       */
535 /*****************************************************************************/
536 GList *
537 gl_merge_read_data(glMergeType type,
538                    GList *field_defs,
539                    gchar *src)
540 {
541         glMergeInput *mp;
542         glMergeRecord *record;
543         GList *record_list = NULL;
544
545         gl_debug (DEBUG_MERGE, "START");
546
547         mp = gl_merge_open (type, field_defs, src);
548         while ( (record = gl_merge_get_record (mp)) != NULL ) {
549                 record_list = g_list_append( record_list, record );
550         }
551         gl_merge_close(mp);
552               
553         gl_debug (DEBUG_MERGE, "END");
554
555         return record_list;
556 }
557
558 /*****************************************************************************/
559 /* Free a list of records.                                                   */
560 /*****************************************************************************/
561 void
562 gl_merge_free_data (GList ** record_list)
563 {
564         GList *p;
565         glMergeRecord *record;
566
567         gl_debug (DEBUG_MERGE, "START");
568
569         for (p = *record_list; p != NULL; p = p->next) {
570                 record = (glMergeRecord *) p->data;
571
572                 gl_merge_free_record( &record );
573
574         }
575
576         g_list_free (*record_list);
577         *record_list = NULL;
578
579         gl_debug (DEBUG_MERGE, "END");
580 }
581
582 /*****************************************************************************/
583 /* Count selected records.                                                   */
584 /*****************************************************************************/
585 gint
586 gl_merge_count_records (GList *record_list)
587 {
588         GList *p;
589         glMergeRecord *record;
590         gint count;
591
592         gl_debug (DEBUG_MERGE, "START");
593
594         count = 0;
595         for ( p=record_list; p!=NULL; p=p->next ) {
596                 record = (glMergeRecord *)p->data;
597
598                 if ( record->select_flag ) count ++;
599         }
600
601         gl_debug (DEBUG_MERGE, "END");
602
603         return count;
604 }
605