sensitise trayicon's 'get mail' and 'exit'
[claws.git] / src / plugins / vcalendar / libical / libical / icalvalue.c
1 /* -*- Mode: C -*- */
2 /*======================================================================
3   FILE: icalvalue.c
4   CREATOR: eric 02 May 1999
5   
6   $Id$
7
8
9  (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
10
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of either: 
13
14     The LGPL as published by the Free Software Foundation, version
15     2.1, available at: http://www.fsf.org/copyleft/lesser.html
16
17   Or:
18
19     The Mozilla Public License Version 1.0. You may obtain a copy of
20     the License at http://www.mozilla.org/MPL/
21
22   The original code is icalvalue.c
23
24   Contributions from:
25      Graham Davison (g.m.davison@computer.org)
26
27
28 ======================================================================*/
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include "icalerror.h"
35 #include "icalmemory.h"
36 #include "icalparser.h"
37 #include "icalenums.h"
38 #include "icalvalueimpl.h"
39
40 #include <stdlib.h> /* for malloc */
41 #include <stdio.h> /* for sprintf */
42 #include <string.h> /* For memset, others */
43 #include <stddef.h> /* For offsetof() macro */
44 #include <errno.h>
45 #include <time.h> /* for mktime */
46 #include <stdlib.h> /* for atoi and atof */
47 #include <limits.h> /* for SHRT_MAX */         
48
49 #if _MAC_OS_
50 #include "icalmemory_strdup.h"
51 #endif
52
53 #define TMP_BUF_SIZE 1024
54
55 void print_datetime_to_string(char* str,  struct icaltimetype *data);
56 void print_date_to_string(char* str,  struct icaltimetype *data);
57 void print_time_to_string(char* str,  struct icaltimetype *data);
58 void print_recur_to_string(char* str,  struct icaltimetype *data);
59
60
61 struct icalvalue_impl*  icalvalue_new_impl(icalvalue_kind kind){
62
63     struct icalvalue_impl* v;
64
65     if ( ( v = (struct icalvalue_impl*)
66            malloc(sizeof(struct icalvalue_impl))) == 0) {
67         icalerror_set_errno(ICAL_NEWFAILED_ERROR);
68         return 0;
69     }
70     
71     strcpy(v->id,"val");
72     
73     v->kind = kind;
74     v->size = 0;
75     v->parent = 0;
76     v->x_value = 0;
77     memset(&(v->data),0,sizeof(v->data));
78     
79     return v;
80
81 }
82
83
84
85 icalvalue*
86 icalvalue_new (icalvalue_kind kind)
87 {
88     return (icalvalue*)icalvalue_new_impl(kind);
89 }
90
91 icalvalue* icalvalue_new_clone(icalvalue* value){
92
93     struct icalvalue_impl* new;
94     struct icalvalue_impl* old = (struct icalvalue_impl*)value;
95
96     new = icalvalue_new_impl(old->kind);
97
98     if (new == 0){
99         return 0;
100     }
101
102     
103     strcpy(new->id, old->id);
104     new->kind = old->kind;
105     new->size = old->size;
106
107     switch (new->kind){
108
109         /* The contents of the attach value may or may not be owned by the 
110          * library. */
111         case ICAL_ATTACH_VALUE: 
112         case ICAL_BINARY_VALUE: 
113         {
114             /* HACK ugh. I don't feel like impleenting this */
115         }
116
117         case ICAL_STRING_VALUE:
118         case ICAL_TEXT_VALUE:
119         case ICAL_CALADDRESS_VALUE:
120         case ICAL_URI_VALUE:
121         {
122             if (old->data.v_string != 0) { 
123                 new->data.v_string=icalmemory_strdup(old->data.v_string);
124
125                 if ( new->data.v_string == 0 ) {
126                     icalvalue_free(new);
127                     return 0;
128                 }                   
129
130             }
131             break;
132         }
133         case ICAL_RECUR_VALUE:
134         {
135             if(old->data.v_recur != 0){
136                 new->data.v_recur = malloc(sizeof(struct icalrecurrencetype));
137
138                 if(new->data.v_recur == 0){
139                     icalvalue_free(new);
140                     return 0;
141                 }
142
143                 memcpy( new->data.v_recur, old->data.v_recur,
144                         sizeof(struct icalrecurrencetype));     
145             }
146             break;
147         }
148
149         default:
150         {
151             /* all of the other types are stored as values, not
152                pointers, so we can just copy the whole structure. */
153
154             new->data = old->data;
155         }
156     }
157
158     return new;
159 }
160
161 char* icalmemory_strdup_and_dequote(const char* str)
162 {
163     const char* p;
164     char* out = (char*)malloc(sizeof(char) * strlen(str) +1);
165     char* pout;
166
167     if (out == 0){
168         return 0;
169     }
170
171     pout = out;
172
173     for (p = str; *p!=0; p++){
174         
175         if( *p == '\\')
176         {
177             p++;
178             switch(*p){
179                 case 0:
180                 {
181                     *pout = '\0';
182                     break;
183
184                 }
185                 case 'n':
186                 {
187                     *pout = '\n';
188                     break;
189                 }
190                 case 'N':
191                 {
192                     *pout = '\n';
193                     break;
194                 }
195                 case '\\':
196                 case ',':
197                 case ';':
198                 {
199                     *pout = *p;
200                     break;
201                 }
202                 default:
203                 {
204                     *pout = ' ';
205                 }               
206             }
207         } else {
208             *pout = *p;
209         }
210
211         pout++;
212         
213     }
214
215     *pout = '\0';
216
217     return out;
218 }
219
220 icalvalue* icalvalue_new_enum(icalvalue_kind kind, int x_type, const char* str)
221 {
222     int e = icalproperty_string_to_enum(str);
223     struct icalvalue_impl *value; 
224
225     if(e != 0 && icalproperty_enum_belongs_to_property(
226                    icalproperty_value_kind_to_kind(kind),e)) {
227         
228         value = icalvalue_new_impl(kind);
229         value->data.v_enum = e;
230     } else {
231         /* Make it an X value */
232         value = icalvalue_new_impl(kind);
233         value->data.v_enum = x_type;
234         icalvalue_set_x(value,str);
235     }
236
237     return value;
238 }
239
240
241 icalvalue* icalvalue_new_from_string_with_error(icalvalue_kind kind,const char* str,icalproperty** error)
242 {
243
244     struct icalvalue_impl *value = 0;
245     
246     icalerror_check_arg_rz(str!=0,"str");
247
248     if (error != 0){
249         *error = 0;
250     }
251
252     switch (kind){
253         
254     case ICAL_ATTACH_VALUE:
255     case ICAL_BINARY_VALUE:     
256     case ICAL_BOOLEAN_VALUE:
257         {
258             /* HACK */
259             value = 0;
260             
261             if (error != 0){
262                 char temp[TMP_BUF_SIZE];
263                 sprintf(temp,"%s Values are not implemented",
264                         icalparameter_kind_to_string(kind)); 
265                 *error = icalproperty_vanew_xlicerror( 
266                                    temp, 
267                                    icalparameter_new_xlicerrortype( 
268                                         ICAL_XLICERRORTYPE_VALUEPARSEERROR), 
269                                    0); 
270             }
271             break;
272         }
273         
274
275     case ICAL_TRANSP_VALUE:
276         value = icalvalue_new_enum(kind, ICAL_TRANSP_X,str);
277         break;
278     case ICAL_METHOD_VALUE:
279         value = icalvalue_new_enum(kind, ICAL_METHOD_X,str);
280         break;
281     case ICAL_STATUS_VALUE:
282         value = icalvalue_new_enum(kind, ICAL_STATUS_X,str);
283         break;
284     case ICAL_ACTION_VALUE:
285         value = icalvalue_new_enum(kind, ICAL_ACTION_X,str);
286         break;
287     case ICAL_CLASS_VALUE:
288         value = icalvalue_new_enum(kind, ICAL_CLASS_X,str);
289         break;
290
291
292     case ICAL_INTEGER_VALUE:
293         {
294             value = icalvalue_new_integer(atoi(str));
295             break;
296         }
297
298     case ICAL_FLOAT_VALUE:
299         {
300             value = icalvalue_new_float(atof(str));
301             break;
302         }
303         
304     case ICAL_UTCOFFSET_VALUE:
305         {
306             value = icalparser_parse_value(kind,str,(icalcomponent*)0);
307             break;
308         }
309         
310     case ICAL_TEXT_VALUE:
311         {
312             char* dequoted_str = icalmemory_strdup_and_dequote(str);
313             value = icalvalue_new_text(dequoted_str);
314             free(dequoted_str);
315             break;
316         }
317         
318         
319     case ICAL_STRING_VALUE:
320         {
321             value = icalvalue_new_string(str);
322             break;
323         }
324         
325     case ICAL_CALADDRESS_VALUE:
326         {
327             value = icalvalue_new_caladdress(str);
328             break;
329         }
330         
331     case ICAL_URI_VALUE:
332         {
333             value = icalvalue_new_uri(str);
334             break;
335         }
336         
337
338     case ICAL_GEO_VALUE:
339         {
340             value = 0;
341             /* HACK */
342             
343             if (error != 0){
344                 char temp[TMP_BUF_SIZE];
345                 sprintf(temp,"GEO Values are not implemented"); 
346                 *error = icalproperty_vanew_xlicerror( 
347                     temp, 
348                     icalparameter_new_xlicerrortype( 
349                         ICAL_XLICERRORTYPE_VALUEPARSEERROR), 
350                     0); 
351             }
352
353             /*icalerror_warn("Parsing GEO properties is unimplmeneted");*/
354
355             break;
356         }
357
358         case ICAL_RECUR_VALUE:
359         {
360             struct icalrecurrencetype rt;
361             rt = icalrecurrencetype_from_string(str);
362             value = icalvalue_new_recur(rt);
363             break;
364         }
365
366         case ICAL_TIME_VALUE:
367         case ICAL_DATE_VALUE:
368         case ICAL_DATETIME_VALUE:
369         case ICAL_DATETIMEDATE_VALUE:
370         {
371             struct icaltimetype tt;
372             tt = icaltime_from_string(str);
373             if(!icaltime_is_null_time(tt)){
374                 value = icalvalue_new_impl(kind);
375                 value->data.v_time = tt;
376             }
377             break;
378         }
379
380         case ICAL_DATETIMEPERIOD_VALUE:
381         {
382             struct icaltimetype tt;
383             struct icalperiodtype p;
384             tt = icaltime_from_string(str);
385             p = icalperiodtype_from_string(str);
386
387             if(!icaltime_is_null_time(tt)){
388                 value = icalvalue_new_datetime(tt);
389             } else if (!icalperiodtype_is_null_period(p)){
390                 value = icalvalue_new_period(p);
391             }            
392
393             break;
394         }
395
396         case ICAL_DURATION_VALUE:
397         {
398             struct icaldurationtype dur = icaldurationtype_from_string(str);
399             
400             if(icaldurationtype_is_null_duration(dur)){
401                 value = 0;
402             } else {
403                 value = icalvalue_new_duration(dur);
404             }
405
406             break;
407         }
408
409          case ICAL_PERIOD_VALUE:
410         {
411           struct icalperiodtype p;
412           p = icalperiodtype_from_string(str);  
413
414           if(!icalperiodtype_is_null_period(p)){
415               value = icalvalue_new_period(p);
416           }
417           break; 
418         }
419         
420         case ICAL_TRIGGER_VALUE:
421         {
422             struct icaltriggertype tr = icaltriggertype_from_string(str);
423             value = icalvalue_new_trigger(tr);
424             break;
425         }
426
427         default:
428         {
429
430             if (error != 0 ){
431                 char temp[TMP_BUF_SIZE];
432
433                 snprintf(temp,TMP_BUF_SIZE,"Unknown type for \'%s\'",str);
434                             
435                 *error = icalproperty_vanew_xlicerror( 
436                     temp, 
437                     icalparameter_new_xlicerrortype( 
438                         ICAL_XLICERRORTYPE_VALUEPARSEERROR), 
439                     0); 
440             }
441
442             icalerror_warn("icalvalue_new_from_string got an unknown value type");
443             value=0;
444         }
445     }
446
447
448     if (error != 0 && *error == 0 && value == 0){
449         char temp[TMP_BUF_SIZE];
450         
451         snprintf(temp,TMP_BUF_SIZE,"Failed to parse value: \'%s\'",str);
452         
453         *error = icalproperty_vanew_xlicerror( 
454             temp, 
455             icalparameter_new_xlicerrortype( 
456                 ICAL_XLICERRORTYPE_VALUEPARSEERROR), 
457             0); 
458     }
459
460
461     return value;
462
463 }
464
465 icalvalue* icalvalue_new_from_string(icalvalue_kind kind,const char* str)
466 {
467     return icalvalue_new_from_string_with_error(kind,str,(icalproperty*)0);
468 }
469
470
471
472 void
473 icalvalue_free (icalvalue* value)
474 {
475     struct icalvalue_impl* v = (struct icalvalue_impl*)value;
476
477     icalerror_check_arg_rv((value != 0),"value");
478
479 #ifdef ICAL_FREE_ON_LIST_IS_ERROR
480     icalerror_assert( (v->parent ==0),"This value is still attached to a property");
481     
482 #else
483     if(v->parent !=0){
484         return;
485     }
486 #endif
487
488     if(v->x_value != 0){
489         free((char *)v->x_value);
490     }
491
492     switch (v->kind){
493         case ICAL_BINARY_VALUE: 
494         case ICAL_ATTACH_VALUE: {
495             /* HACK ugh. This will be tough to implement */
496         }
497         case ICAL_TEXT_VALUE:
498         case ICAL_CALADDRESS_VALUE:
499         case ICAL_URI_VALUE:
500         {
501             if (v->data.v_string != 0) { 
502                 free((void*)v->data.v_string);
503                 v->data.v_string = 0;
504             }
505             break;
506         }
507         case ICAL_RECUR_VALUE:
508         {
509             if(v->data.v_recur != 0){
510                 free((void*)v->data.v_recur);
511                 v->data.v_recur = 0;
512             }
513             break;
514         }
515
516         default:
517         {
518             /* Nothing to do */
519         }
520     }
521
522     v->kind = ICAL_NO_VALUE;
523     v->size = 0;
524     v->parent = 0;
525     memset(&(v->data),0,sizeof(v->data));
526     v->id[0] = 'X';
527     free(v);
528 }
529
530 int
531 icalvalue_is_valid (icalvalue* value)
532 {
533     /*struct icalvalue_impl* v = (struct icalvalue_impl*)value;*/
534     
535     if(value == 0){
536         return 0;
537     }
538     
539     return 1;
540 }
541
542 char* icalvalue_binary_as_ical_string(icalvalue* value) {
543
544     char* str;
545     icalerror_check_arg_rz( (value!=0),"value");
546
547     str = (char*)icalmemory_tmp_buffer(60);
548     sprintf(str,"icalvalue_binary_as_ical_string is not implemented yet");
549
550     return str;
551 }
552
553
554 #define MAX_INT_DIGITS 12 /* Enough for 2^32 + sign*/ 
555 char* icalvalue_int_as_ical_string(icalvalue* value) {
556     
557     int data;
558     char* str = (char*)icalmemory_tmp_buffer(MAX_INT_DIGITS); 
559
560     icalerror_check_arg_rz( (value!=0),"value");
561
562     data = icalvalue_get_integer(value);
563         
564     snprintf(str,MAX_INT_DIGITS,"%d",data);
565
566     return str;
567 }
568
569 char* icalvalue_utcoffset_as_ical_string(icalvalue* value)
570 {    
571     int data,h,m,s;
572     char sign;
573     char* str = (char*)icalmemory_tmp_buffer(9);
574
575     icalerror_check_arg_rz( (value!=0),"value");
576
577     data = icalvalue_get_utcoffset(value);
578
579     if (abs(data) == data){
580         sign = '+';
581     } else {
582         sign = '-';
583     }
584
585     h = data/3600;
586     m = (data - (h*3600))/ 60;
587     s = (data - (h*3600) - (m*60));
588
589     sprintf(str,"%c%02d%02d%02d",sign,abs(h),abs(m),abs(s));
590
591     return str;
592 }
593
594 char* icalvalue_string_as_ical_string(icalvalue* value) {
595
596     const char* data;
597     char* str = 0;
598     icalerror_check_arg_rz( (value!=0),"value");
599     data = ((struct icalvalue_impl*)value)->data.v_string;
600
601     str = (char*)icalmemory_tmp_buffer(strlen(data)+1);   
602
603     strcpy(str,data);
604
605     return str;
606 }
607
608
609 char* icalvalue_recur_as_ical_string(icalvalue* value) 
610 {
611     struct icalvalue_impl *impl = (struct icalvalue_impl*)value;
612     struct icalrecurrencetype *recur = impl->data.v_recur;
613
614     return icalrecurrencetype_as_string(recur);
615 }
616
617 char* icalvalue_text_as_ical_string(icalvalue* value) {
618
619     char *str;
620     char *str_p;
621     char *rtrn;
622     const char *p;
623     size_t buf_sz;
624     int line_length;
625
626     line_length = 0;
627
628     buf_sz = strlen(((struct icalvalue_impl*)value)->data.v_string)+1;
629
630     str_p = str = (char*)icalmemory_new_buffer(buf_sz);
631
632     if (str_p == 0){
633       return 0;
634     }
635
636     for(p=((struct icalvalue_impl*)value)->data.v_string; *p!=0; p++){
637
638         switch(*p){
639             case '\n': {
640                 icalmemory_append_string(&str,&str_p,&buf_sz,"\\n");
641                 line_length+=3;
642                 break;
643             }
644
645             case '\t': {
646                 icalmemory_append_string(&str,&str_p,&buf_sz,"\\t");
647                 line_length+=3;
648                 break;
649             }
650             case '\r': {
651                 icalmemory_append_string(&str,&str_p,&buf_sz,"\\r");
652                 line_length+=3;
653                 break;
654             }
655             case '\b': {
656                 icalmemory_append_string(&str,&str_p,&buf_sz,"\\b");
657                 line_length+=3;
658                 break;
659             }
660             case '\f': {
661                 icalmemory_append_string(&str,&str_p,&buf_sz,"\\f");
662                 line_length+=3;
663                 break;
664             }
665
666             case ';':
667             case ',':{
668                 icalmemory_append_char(&str,&str_p,&buf_sz,'\\');
669                 icalmemory_append_char(&str,&str_p,&buf_sz,*p);
670                 line_length+=3;
671                 break;
672             }
673
674             case '"':{
675                 icalmemory_append_char(&str,&str_p,&buf_sz,'\\');
676                 icalmemory_append_char(&str,&str_p,&buf_sz,*p);
677                 line_length+=3;
678                 break;
679             }
680
681             default: {
682                 icalmemory_append_char(&str,&str_p,&buf_sz,*p);
683                 line_length++;
684             }
685         }
686
687         if (line_length > 65 && *p == ' '){
688             icalmemory_append_string(&str,&str_p,&buf_sz,"\n ");
689             line_length=0;
690         }
691
692
693         if (line_length > 75){
694             icalmemory_append_string(&str,&str_p,&buf_sz,"\n ");
695             line_length=0;
696         }
697
698     }
699
700     /* Assume the last character is not a '\0' and add one. We could
701        check *str_p != 0, but that would be an uninitialized memory
702        read. */
703
704
705     icalmemory_append_char(&str,&str_p,&buf_sz,'\0');
706
707     rtrn = icalmemory_tmp_copy(str);
708
709     icalmemory_free_buffer(str);
710
711     return rtrn;
712 }
713
714
715 char* icalvalue_attach_as_ical_string(icalvalue* value) {
716
717     struct icalattachtype a;
718     char * str;
719
720     icalerror_check_arg_rz( (value!=0),"value");
721
722     a = icalvalue_get_attach(value);
723
724     if (a.binary != 0) {
725         return  icalvalue_binary_as_ical_string(value);
726     } else if (a.base64 != 0) {
727         str = (char*)icalmemory_tmp_buffer(strlen(a.base64)+1);
728         strcpy(str,a.base64);
729         return str;
730     } else if (a.url != 0){
731         return icalvalue_string_as_ical_string(value);
732     } else {
733         icalerrno = ICAL_MALFORMEDDATA_ERROR;
734         return 0;
735     }
736 }
737
738
739 char* icalvalue_duration_as_ical_string(icalvalue* value) {
740
741     struct icaldurationtype data;
742
743     icalerror_check_arg_rz( (value!=0),"value");
744     data = icalvalue_get_duration(value);
745
746     return icaldurationtype_as_ical_string(data);
747 }
748
749 void print_time_to_string(char* str,  struct icaltimetype *data)
750 {
751     char temp[20];
752
753     if (data->is_utc == 1){
754         sprintf(temp,"%02d%02d%02dZ",data->hour,data->minute,data->second);
755     } else {
756         sprintf(temp,"%02d%02d%02d",data->hour,data->minute,data->second);
757     }   
758
759     strcat(str,temp);
760 }
761
762  
763 char* icalvalue_time_as_ical_string(icalvalue* value) {
764
765     struct icaltimetype data;
766     char* str;
767     icalerror_check_arg_rz( (value!=0),"value");
768     data = icalvalue_get_time(value);
769     
770     str = (char*)icalmemory_tmp_buffer(8);
771
772     str[0] = 0;
773     print_time_to_string(str,&data);
774
775     return str;
776 }
777
778 void print_date_to_string(char* str,  struct icaltimetype *data)
779 {
780     char temp[20];
781
782     sprintf(temp,"%04d%02d%02d",data->year,data->month,data->day);
783
784     strcat(str,temp);
785 }
786
787 char* icalvalue_date_as_ical_string(icalvalue* value) {
788
789     struct icaltimetype data;
790     char* str;
791     icalerror_check_arg_rz( (value!=0),"value");
792     data = icalvalue_get_date(value);
793
794     str = (char*)icalmemory_tmp_buffer(9);
795  
796     str[0] = 0;
797     print_date_to_string(str,&data);
798    
799     return str;
800 }
801
802 void print_datetime_to_string(char* str,  struct icaltimetype *data)
803 {
804     print_date_to_string(str,data);
805     strcat(str,"T");
806     print_time_to_string(str,data);
807
808 }
809
810 const char* icalvalue_datetime_as_ical_string(icalvalue* value) {
811     
812     struct icaltimetype data;
813     char* str;
814     icalvalue_kind kind = icalvalue_isa(value);    
815
816     icalerror_check_arg_rz( (value!=0),"value");
817
818
819     if( !(kind == ICAL_DATETIMEDATE_VALUE ||
820           kind == ICAL_DATE_VALUE ||
821           kind == ICAL_DATETIME_VALUE ||
822           kind == ICAL_TIME_VALUE))
823         {
824             icalerror_set_errno(ICAL_BADARG_ERROR);
825             return 0;
826         }
827
828     data = icalvalue_get_datetime(value);
829
830     str = (char*)icalmemory_tmp_buffer(20);
831  
832     str[0] = 0;
833
834     print_datetime_to_string(str,&data);
835    
836     return str;
837
838 }
839
840
841 const char* icalvalue_datetimedate_as_ical_string(icalvalue* value) {
842
843     struct icaltimetype data;
844     icalerror_check_arg_rz( (value!=0),"value");
845     data = icalvalue_get_datetime(value);
846
847     if (data.is_date == 1){
848         return icalvalue_date_as_ical_string(value);
849     } else {
850         return icalvalue_datetime_as_ical_string(value);
851     }
852 }
853
854
855 char* icalvalue_float_as_ical_string(icalvalue* value) {
856
857     float data;
858     char* str;
859     icalerror_check_arg_rz( (value!=0),"value");
860     data = icalvalue_get_float(value);
861
862     str = (char*)icalmemory_tmp_buffer(15);
863
864     sprintf(str,"%f",data);
865
866     return str;
867 }
868
869 char* icalvalue_geo_as_ical_string(icalvalue* value) {
870
871     struct icalgeotype data;
872     char* str;
873     icalerror_check_arg_rz( (value!=0),"value");
874
875     data = icalvalue_get_geo(value);
876
877     str = (char*)icalmemory_tmp_buffer(25);
878
879     sprintf(str,"%f;%f",data.lat,data.lon);
880
881     return str;
882 }
883
884 const char* icalvalue_datetimeperiod_as_ical_string(icalvalue* value) {
885     struct icaldatetimeperiodtype dtp = icalvalue_get_datetimeperiod(value);
886
887     icalerror_check_arg_rz( (value!=0),"value");
888
889     if(!icaltime_is_null_time(dtp.time)){
890         return icaltime_as_ical_string(dtp.time);
891     } else {
892         return icalperiodtype_as_ical_string(dtp.period);
893     }
894 }
895
896 const char* icalvalue_period_as_ical_string(icalvalue* value) {
897     struct icalperiodtype data;
898     icalerror_check_arg_rz( (value!=0),"value");
899     data = icalvalue_get_period(value);
900
901     return icalperiodtype_as_ical_string(data);
902
903 }
904
905 char* icalvalue_trigger_as_ical_string(icalvalue* value) {
906
907     struct icaltriggertype data;
908
909     icalerror_check_arg_rz( (value!=0),"value");
910     data = icalvalue_get_trigger(value);
911
912     if(!icaltime_is_null_time(data.time)){
913         return icaltime_as_ical_string(data.time);
914     } else {
915         return icaldurationtype_as_ical_string(data.duration);
916     }   
917
918 }
919
920 const char*
921 icalvalue_as_ical_string (icalvalue* value)
922 {
923     struct icalvalue_impl* v = (struct icalvalue_impl*)value;
924
925     v=v;
926
927     if(value == 0){
928         return 0;
929     }
930
931     switch (v->kind){
932
933     case ICAL_ATTACH_VALUE:
934         return icalvalue_attach_as_ical_string(value);
935         
936     case ICAL_BINARY_VALUE:
937         return icalvalue_binary_as_ical_string(value);
938         
939     case ICAL_BOOLEAN_VALUE:
940     case ICAL_INTEGER_VALUE:
941         return icalvalue_int_as_ical_string(value);                  
942         
943     case ICAL_UTCOFFSET_VALUE:
944         return icalvalue_utcoffset_as_ical_string(value);                  
945         
946     case ICAL_TEXT_VALUE:
947         return icalvalue_text_as_ical_string(value);
948         
949     case ICAL_STRING_VALUE:
950     case ICAL_URI_VALUE:
951     case ICAL_CALADDRESS_VALUE:
952         return icalvalue_string_as_ical_string(value);
953         
954     case ICAL_DATE_VALUE:
955         return icalvalue_date_as_ical_string(value);
956     case ICAL_DATETIME_VALUE:
957         return icalvalue_datetime_as_ical_string(value);
958     case ICAL_DATETIMEDATE_VALUE:
959         return icalvalue_datetimedate_as_ical_string(value);
960     case ICAL_DURATION_VALUE:
961         return icalvalue_duration_as_ical_string(value);
962     case ICAL_TIME_VALUE:
963         return icalvalue_time_as_ical_string(value);
964         
965     case ICAL_PERIOD_VALUE:
966         return icalvalue_period_as_ical_string(value);
967     case ICAL_DATETIMEPERIOD_VALUE:
968         return icalvalue_datetimeperiod_as_ical_string(value);
969         
970     case ICAL_FLOAT_VALUE:
971         return icalvalue_float_as_ical_string(value);
972         
973     case ICAL_GEO_VALUE:
974         return icalvalue_geo_as_ical_string(value);
975         
976     case ICAL_RECUR_VALUE:
977         return icalvalue_recur_as_ical_string(value);
978         
979     case ICAL_TRIGGER_VALUE:
980         return icalvalue_trigger_as_ical_string(value);
981         
982     case ICAL_ACTION_VALUE:
983     case ICAL_METHOD_VALUE:
984     case ICAL_STATUS_VALUE:
985     case ICAL_TRANSP_VALUE:
986     case ICAL_CLASS_VALUE:
987         if(v->x_value !=0){
988             return icalmemory_tmp_copy(v->x_value);
989         }
990
991         return icalproperty_enum_to_string(v->data.v_enum);
992         
993     case ICAL_X_VALUE: 
994         return icalmemory_tmp_copy(v->x_value);
995
996     case ICAL_NO_VALUE:
997     default:
998         {
999             return 0;
1000         }
1001     }
1002 }
1003
1004
1005 icalvalue_kind
1006 icalvalue_isa (icalvalue* value)
1007 {
1008     struct icalvalue_impl* v = (struct icalvalue_impl*)value;
1009
1010     if(value == 0){
1011         return ICAL_NO_VALUE;
1012     }
1013
1014     return v->kind;
1015 }
1016
1017
1018 int
1019 icalvalue_isa_value (void* value)
1020 {
1021     struct icalvalue_impl *impl = (struct icalvalue_impl *)value;
1022
1023     icalerror_check_arg_rz( (value!=0), "value");
1024
1025     if (strcmp(impl->id,"val") == 0) {
1026         return 1;
1027     } else {
1028         return 0;
1029     }
1030 }
1031
1032
1033 int icalvalue_is_time(icalvalue* a) {
1034     icalvalue_kind kind = icalvalue_isa(a);
1035
1036     if(kind == ICAL_DATETIMEDATE_VALUE ||
1037        kind == ICAL_DATETIME_VALUE ||
1038        kind == ICAL_DATE_VALUE ||
1039        kind == ICAL_TIME_VALUE ){
1040         return 1;
1041     }
1042
1043     return 0;
1044
1045 }
1046
1047 icalparameter_xliccomparetype
1048 icalvalue_compare(icalvalue* a, icalvalue *b)
1049 {
1050     struct icalvalue_impl *impla = (struct icalvalue_impl *)a;
1051     struct icalvalue_impl *implb = (struct icalvalue_impl *)b;
1052
1053     icalerror_check_arg_rz( (a!=0), "a");
1054     icalerror_check_arg_rz( (b!=0), "b");
1055
1056     /* Not the same type; they can only be unequal */
1057     if( ! (icalvalue_is_time(a) && icalvalue_is_time(b)) &&
1058         icalvalue_isa(a) != icalvalue_isa(b)){
1059         return ICAL_XLICCOMPARETYPE_NOTEQUAL;
1060     }
1061
1062     switch (icalvalue_isa(a)){
1063
1064         case ICAL_ATTACH_VALUE:
1065         case ICAL_BINARY_VALUE:
1066
1067         case ICAL_BOOLEAN_VALUE:
1068         {
1069             if (icalvalue_get_boolean(a) == icalvalue_get_boolean(b)){
1070                 return ICAL_XLICCOMPARETYPE_EQUAL;
1071             } else {
1072                 return ICAL_XLICCOMPARETYPE_NOTEQUAL;
1073             }
1074         }
1075
1076         case ICAL_FLOAT_VALUE:
1077         {
1078             if (impla->data.v_float > implb->data.v_float){
1079                 return ICAL_XLICCOMPARETYPE_GREATER;
1080             } else if (impla->data.v_float < implb->data.v_float){
1081                 return ICAL_XLICCOMPARETYPE_LESS;
1082             } else {
1083                 return ICAL_XLICCOMPARETYPE_EQUAL;
1084             }
1085         }
1086
1087         case ICAL_INTEGER_VALUE:
1088         case ICAL_UTCOFFSET_VALUE:
1089         {
1090             if (impla->data.v_int > implb->data.v_int){
1091                 return ICAL_XLICCOMPARETYPE_GREATER;
1092             } else if (impla->data.v_int < implb->data.v_int){
1093                 return ICAL_XLICCOMPARETYPE_LESS;
1094             } else {
1095                 return ICAL_XLICCOMPARETYPE_EQUAL;
1096             }
1097         }
1098
1099         case ICAL_DURATION_VALUE: 
1100         {
1101             int a = icaldurationtype_as_int(impla->data.v_duration);
1102             int b = icaldurationtype_as_int(implb->data.v_duration);
1103
1104             if (a > b){
1105                 return ICAL_XLICCOMPARETYPE_GREATER;
1106             } else if (a < b){
1107                 return ICAL_XLICCOMPARETYPE_LESS;
1108             } else {
1109                 return ICAL_XLICCOMPARETYPE_EQUAL;
1110             }
1111         }           
1112
1113
1114         case ICAL_TEXT_VALUE:
1115         case ICAL_URI_VALUE:
1116         case ICAL_CALADDRESS_VALUE:
1117         case ICAL_TRIGGER_VALUE:
1118         case ICAL_DATE_VALUE:
1119         case ICAL_DATETIME_VALUE:
1120         case ICAL_DATETIMEDATE_VALUE:
1121         case ICAL_TIME_VALUE:
1122         case ICAL_DATETIMEPERIOD_VALUE:
1123         {
1124             int r;
1125
1126             r =  strcmp(icalvalue_as_ical_string(a),
1127                           icalvalue_as_ical_string(b));
1128
1129             if (r > 0) {        
1130                 return ICAL_XLICCOMPARETYPE_GREATER;
1131             } else if (r < 0){
1132                 return ICAL_XLICCOMPARETYPE_LESS;
1133             } else {
1134                 return ICAL_XLICCOMPARETYPE_EQUAL;
1135             }
1136
1137                 
1138         }
1139
1140         case ICAL_METHOD_VALUE:
1141         {
1142             if (icalvalue_get_method(a) == icalvalue_get_method(b)){
1143                 return ICAL_XLICCOMPARETYPE_EQUAL;
1144             } else {
1145                 return ICAL_XLICCOMPARETYPE_NOTEQUAL;
1146             }
1147
1148         }
1149
1150         case ICAL_STATUS_VALUE:
1151         {
1152             if (icalvalue_get_status(a) == icalvalue_get_status(b)){
1153                 return ICAL_XLICCOMPARETYPE_EQUAL;
1154             } else {
1155                 return ICAL_XLICCOMPARETYPE_NOTEQUAL;
1156             }
1157
1158         }
1159
1160         case ICAL_PERIOD_VALUE:
1161         case ICAL_GEO_VALUE:
1162         case ICAL_RECUR_VALUE:
1163         case ICAL_NO_VALUE:
1164         default:
1165         {
1166             icalerror_warn("Comparison not implemented for value type");
1167             return ICAL_XLICCOMPARETYPE_REGEX+1; /* HACK */
1168         }
1169     }   
1170
1171 }
1172
1173 void icalvalue_set_parent(icalvalue* value,
1174                              icalproperty* property)
1175 {
1176     struct icalvalue_impl* v = (struct icalvalue_impl*)value;
1177
1178     v->parent = property;
1179
1180 }
1181
1182 icalproperty* icalvalue_get_parent(icalvalue* value)
1183 {
1184     struct icalvalue_impl* v = (struct icalvalue_impl*)value;
1185
1186
1187     return v->parent;
1188 }
1189
1190
1191
1192 /* The remaining interfaces are 'new', 'set' and 'get' for each of the value
1193    types */
1194
1195
1196 /* Everything below this line is machine generated. Do not edit. */