add Summary->Next/Prev labeled message
[claws.git] / src / mgutils.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2001 Match Grun
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * General functions for create common address book entries.
22  */
23
24 #include <sys/stat.h>
25 #include <stdio.h>
26 #include <glib.h>
27
28 #include "addressitem.h"
29 #include "mgutils.h"
30
31 /*
32 * Create new address item.
33 */
34 AddressItem *mgu_create_address_item( AddressObjectType type ) {
35         AddressItem *item;
36         item = g_new( AddressItem, 1 );
37         ADDRESS_OBJECT(item)->type = type;
38         item->name = NULL;
39         item->address = NULL;
40         item->remarks = NULL;
41         item->externalID = NULL;
42         item->categoryID = ADDRESS_ITEM_CAT_UNKNOWN;
43         return item;
44 }
45
46 /*
47 * Create new address item.
48 */
49 AddressItem *mgu_create_address( void ) {
50         AddressItem *item;
51         item = g_new( AddressItem, 1 );
52         ADDRESS_OBJECT(item)->type = ADDR_ITEM;
53         item->name = NULL;
54         item->address = NULL;
55         item->remarks = NULL;
56         item->externalID = NULL;
57         item->categoryID = ADDRESS_ITEM_CAT_UNKNOWN;
58         return item;
59 }
60
61 /*
62 * Create copy of specified address item.
63 */
64 AddressItem *mgu_copy_address_item( AddressItem *item ) {
65         AddressItem *itemNew = NULL;
66         if( item ) {
67                 itemNew = mgu_create_address_item( ADDRESS_OBJECT(item)->type );
68                 itemNew->name = g_strdup( item->name );
69                 itemNew->address = g_strdup( item->address );
70                 itemNew->remarks = g_strdup( item->remarks );
71                 itemNew->externalID = g_strdup( item->externalID );
72                 itemNew->categoryID = item->categoryID;
73         }
74         return itemNew;
75 }
76
77 /*
78 * Free address item.
79 */
80 void mgu_free_address( AddressItem *item ) {
81         g_return_if_fail( item != NULL );
82
83         /* Free internal stuff */
84         g_free( item->name );
85         g_free( item->address );
86         g_free( item->remarks );
87         g_free( item->externalID );
88         item->name = NULL;
89         item->address = NULL;
90         item->remarks = NULL;
91         item->externalID = NULL;
92         item->categoryID = ADDRESS_ITEM_CAT_UNKNOWN;
93
94         /* Now release item */
95         g_free( item );
96 }
97
98 /*
99 * Refresh internal variables to force a reload.
100 */
101 void mgu_refresh_cache( AddressCache *cache ) {
102         cache->dataRead = FALSE;
103         cache->modified = TRUE;
104         cache->modifyTime = 0;
105 }
106
107 /*
108 * Free up address list.
109 */
110 void mgu_free_address_list( GList *addrList ) {
111         AddressItem *item;
112         GList *node;
113
114         /* Free data in the list */
115         node = addrList;
116         while( node ) {
117                 item = node->data;
118                 mgu_free_address( item );
119                 node->data = NULL;
120                 node = g_list_next( node );
121         }
122
123         /* Now release linked list object */
124         g_list_free( addrList );
125 }
126
127 /*
128 * Clear the cache.
129 */
130 void mgu_clear_cache( AddressCache *cache ) {
131         AddressItem *item;
132         GList *node;
133         g_return_if_fail( cache != NULL );
134
135         /* Free data in the list */
136         mgu_free_address_list( cache->addressList );
137         cache->addressList = NULL;
138         mgu_refresh_cache( cache );
139 }
140
141 /*
142 * Clear the cache by setting pointers to NULL and free list.
143 * Note that individual items are not free'd.
144 */
145 void mgu_clear_cache_null( AddressCache *cache ) {
146         GList *node;
147         g_return_if_fail( cache != NULL );
148
149         /* Free data in the list */
150         node = cache->addressList;
151         while( node ) {
152                 node->data = NULL;
153                 node = g_list_next( node );
154         }
155
156         /* Now release linked list object */
157         g_list_free( cache->addressList );
158         cache->addressList = NULL;
159 }
160
161 /*
162 * Create new cache.
163 */
164 AddressCache *mgu_create_cache( void ) {
165         AddressCache *cache;
166         cache = g_new( AddressCache, 1 );
167         cache->addressList = NULL;
168         cache->dataRead = FALSE;
169         cache->modified = FALSE;
170         cache->modifyTime = 0;
171         return cache;
172 }
173
174 /*
175 * Create new address item.
176 */
177 void mgu_free_cache( AddressCache *cache ) {
178         mgu_clear_cache( cache );
179         cache->addressList = NULL;
180 }
181
182 /*
183 * Print address item.
184 */
185 void mgu_print_address( AddressItem *item, FILE *stream ) {
186         g_return_if_fail( item != NULL );
187         fprintf( stream, "addr item:\n" );
188         fprintf( stream, "\tname: '%s'\n", item->name );
189         fprintf( stream, "\taddr: '%s'\n", item->address );
190         fprintf( stream, "\trems: '%s'\n", item->remarks );
191         fprintf( stream, "\tid  : '%s'\n", item->externalID );
192         fprintf( stream, "\tcatg: '%d'\n", item->categoryID );
193         fprintf( stream, "---\n" );
194 }
195
196 /*
197 * Print linked list containing address item(s).
198 */
199 void mgu_print_address_list( GList *addrList, FILE *stream ) {
200         GList *node;
201         g_return_if_fail( addrList != NULL );
202
203         /* Now process the list */
204         node = addrList;
205         while( node ) {
206                 gpointer *gptr = node->data;
207                 AddressItem *item = ( AddressItem * ) gptr;
208                 mgu_print_address( item, stream );              
209                 node = g_list_next( node );
210         }
211 }
212
213 /*
214 * Print address cache.
215 */
216 void mgu_print_cache( AddressCache *cache, FILE *stream ) {
217         GList *node;
218         g_return_if_fail( cache != NULL );
219         fprintf( stream, "AddressCache:\n" );
220         fprintf( stream, "modified : %s\n", cache->modified ? "yes" : "no" );
221         fprintf( stream, "data read: %s\n", cache->dataRead ? "yes" : "no" );
222
223         /* Now process the list */
224         node = cache->addressList;
225         while( node ) {
226                 gpointer *gptr;
227                 AddressItem *item;
228                 gptr = node->data;
229                 item = ( AddressItem * ) gptr;
230                 mgu_print_address( item, stream );              
231                 node = g_list_next( node );
232         }
233 }
234
235 /*
236 * Dump linked list of character strings (for debug).
237 */
238 void mgu_print_list( GSList *list, FILE *stream ) {
239         GSList *node = list;
240         while( node ) {
241                 fprintf( stream, "\t- >%s<\n", node->data );
242                 node = g_slist_next( node );
243         }
244 }
245
246 /*
247 * Dump linked list of character strings (for debug).
248 */
249 void mgu_print_dlist( GList *list, FILE *stream ) {
250         GList *node = list;
251         while( node ) {
252                 fprintf( stream, "\t- >%s<\n", node->data );
253                 node = g_list_next( node );
254         }
255 }
256
257 /*
258 * Check whether file has changed by comparing with cache.
259 * return:       TRUE if file has changed.
260 */
261 gboolean mgu_check_file( AddressCache *cache, gchar *path ) {
262         gboolean retVal;
263         struct stat filestat;
264         retVal = TRUE;
265         if( path ) {
266                 if( 0 == lstat( path, &filestat ) ) {
267                         if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
268                 }
269         }
270         return retVal;
271 }
272
273 /*
274 * Save file time to cache.
275 * return:       TRUE if time marked.
276 */
277 gboolean mgu_mark_cache( AddressCache *cache, gchar *path ) {
278         gboolean retVal = FALSE;
279         struct stat filestat;
280         if( path ) {
281                 if( 0 == lstat( path, &filestat ) ) {
282                         cache->modifyTime = filestat.st_mtime;
283                         retVal = TRUE;
284                 }
285         }
286         return retVal;
287 }
288
289 /*
290 * Free linked list of character strings.
291 */
292 void mgu_free_list( GSList *list ) {
293         GSList *node = list;
294         while( node ) {
295                 g_free( node->data );
296                 node->data = NULL;
297                 node = g_slist_next( node );
298         }
299         g_slist_free( list );
300 }
301
302 /*
303 * Free linked list of character strings.
304 */
305 void mgu_free_dlist( GList *list ) {
306         GList *node = list;
307         while( node ) {
308                 g_free( node->data );
309                 node->data = NULL;
310                 node = g_list_next( node );
311         }
312         g_list_free( list );
313 }
314
315 /*
316 * Coalesce linked list of characaters into one long string.
317 */
318 gchar *mgu_list_coalesce( GSList *list ) {
319         gchar *str = NULL;
320         gchar *buf = NULL;
321         gchar *start = NULL;
322         GSList *node = NULL;
323         gint len;
324
325         if( ! list ) return NULL;
326
327         // Calculate maximum length of text
328         len = 0;
329         node = list;
330         while( node ) {
331                 str = node->data;
332                 len += 1 + strlen( str );
333                 node = g_slist_next( node );
334         }
335
336         // Create new buffer.
337         buf = g_new( gchar, len+1 );
338         start = buf;
339         node = list;
340         while( node ) {
341                 str = node->data;
342                 len = strlen( str );
343                 strcpy( start, str );
344                 start += len;
345                 node = g_slist_next( node );
346         }
347         return buf;
348 }
349
350 /*
351 * Add address item to cache.
352 */
353 void mgu_add_cache( AddressCache *cache, AddressItem *addrItem ) {
354         cache->addressList = g_list_append( cache->addressList, addrItem );
355         cache->modified = TRUE;
356 }
357
358 struct mgu_error_entry {
359         gint    e_code;
360         gchar   *e_reason;
361 };
362
363 static const struct mgu_error_entry mgu_error_list[] = {
364         { MGU_SUCCESS,          "Success" },
365         { MGU_BAD_ARGS,         "Bad arguments" },
366         { MGU_NO_FILE,          "File not specified" },
367         { MGU_OPEN_FILE,        "Error opening file" },
368         { MGU_ERROR_READ,       "Error reading file" },
369         { MGU_EOF,              "End of file encountered" },
370         { MGU_OO_MEMORY,        "Error allocating memory" },
371         { MGU_BAD_FORMAT,       "Bad file format" },
372         { MGU_LDAP_CONNECT,     "Error connecting to LDAP server" },
373         { MGU_LDAP_INIT,        "Error initializing LDAP" },
374         { MGU_LDAP_BIND,        "Error binding to LDAP server" },
375         { MGU_LDAP_SEARCH,      "Error searching LDAP database" },
376         { MGU_LDAP_TIMEOUT,     "Timeout performing LDAP operation" },
377         { MGU_LDAP_CRITERIA,    "Error in LDAP search criteria" },
378         { MGU_LDAP_CRITERIA,    "Error in LDAP search criteria" },
379         { MGU_LDAP_NOENTRIES,   "No LDAP entries found for search criteria" },
380         { -999,                 NULL }
381 };
382
383 static const struct mgu_error_entry *mgu_error_find( gint err ) {
384         gint i;
385         for ( i = 0; mgu_error_list[i].e_code != -999; i++ ) {
386                 if ( err == mgu_error_list[i].e_code )
387                         return & mgu_error_list[i];
388         }
389         return NULL;
390 }
391
392 /*
393 * Return error message for specified error code.
394 */
395 gchar *mgu_error2string( gint err ) {
396         const struct mgu_error_entry *e;
397         e = mgu_error_find( err );
398         return ( e != NULL ) ? e->e_reason : "Unknown error";
399 }
400
401 /*
402 * End of Source.
403 */