Back to index

lightning-sunbird  0.9+nobinonly
vcomponent.cpp
Go to the documentation of this file.
00001 
00009 #ifndef VCOMPONENT_H
00010 #include "vcomponent.h"
00011 #endif
00012 
00013 #ifndef ICALVALUE_CXX_H
00014 #include "icalvalue_cxx.h"
00015 #endif
00016 
00017 #ifndef ICALPROPERTY_CXX_H
00018 #include "icalproperty_cxx.h"
00019 #endif
00020 
00021 #ifndef ICALPARAMETER_CXX_H
00022 #include "icalparameter_cxx.h"
00023 #endif
00024 #include <stdlib.h>
00025 #include <string.h>
00026 
00027 #include <exception>
00028 
00029 VComponent::VComponent() throw(icalerrorenum) : imp(icalcomponent_new(ICAL_ANY_COMPONENT)) {
00030 }
00031 VComponent::VComponent(const VComponent& v) throw(icalerrorenum) {
00032   imp = icalcomponent_new_clone(v.imp);
00033   if (!imp) throw icalerrno;
00034 }
00035 
00036 VComponent& VComponent::operator=(const VComponent& v) throw(icalerrorenum) {
00037        if (this == &v) return *this;
00038 
00039        if (imp != NULL)
00040        {
00041               icalcomponent_free(imp);
00042               imp = icalcomponent_new_clone(v.imp);
00043        if (!imp) throw icalerrno;
00044        }
00045 
00046        return *this;
00047 }
00048 
00049 VComponent::~VComponent(){
00050        if (imp)
00051           icalcomponent_free(imp);
00052 }
00053 
00054 VComponent::VComponent(icalcomponent* v) throw (icalerrorenum) : imp(v){
00055 }
00056 
00057 /* char* returned is in the ring buffer. caller doesn't have to free it */
00058 char* VComponent::quote_ical_string(char *str){
00059     const char* p;
00060     size_t  buf_sz;
00061     buf_sz = strlen(str) * 2;      /* assume worse case scenarios. otherwise, we have to parse the string and count \ */
00062     char* out = (char*)icalmemory_new_buffer(buf_sz);    /* memory is from the ring buffer */
00063     char* pout;
00064 
00065     if (out == 0){
00066         return 0;
00067     }
00068 
00069     pout = out;
00070 
00071     for (p = str; *p!=0; p++){
00072 
00073         if( *p == '\\'){
00074             *pout++ = '\\';
00075        }
00076        *pout++ = *p;
00077 
00078     }
00079     *pout++ = '\0';
00080 
00081     return out;
00082 }
00083 
00093 VComponent::VComponent(string str)  throw (icalerrorenum) {
00094        // Fix for BUG #15647, but breaks fix for BUG #15596.  Attempting a UI fix for cal-4.0.
00095        //char* quoted_str = quote_ical_string((char *)str);
00096        //imp = icalcomponent_new_from_string(quoted_str);
00097        imp = icalcomponent_new_from_string(str);
00098 
00099        if (!imp) throw icalerrno;
00100 }
00101 
00102 VComponent::VComponent(icalcomponent_kind kind)  throw(icalerrorenum) {
00103   imp = icalcomponent_new(kind);
00104 
00105   if (!imp) throw icalerrno;
00106 }
00107 
00108 
00109 string VComponent::as_ical_string()  throw(icalerrorenum) {
00110   char *str = icalcomponent_as_ical_string(imp);
00111 
00112   if (!str) throw icalerrno;
00113 
00114   return(str);
00115 }
00116 
00117 
00118 bool VComponent::is_valid(){
00119        if (imp == NULL) return false;
00120        return (icalcomponent_is_valid(imp) ? true : false);
00121 }
00122 
00123 icalcomponent_kind VComponent::isa(){
00124        return icalcomponent_isa(imp);
00125 }
00126 
00127 int VComponent::isa_component(void* component){
00128        return icalcomponent_isa_component(component);
00129 }
00130 
00131 void VComponent::new_from_string(string str){
00132        if (imp != NULL) icalcomponent_free(imp);
00133        imp = icalcomponent_new_from_string(str);
00134 }
00135 
00136 /* Working with properties */
00137 void VComponent::add_property(ICalProperty* property){
00138        icalcomponent_add_property(imp, *property);
00139 }
00140 void VComponent::remove_property(ICalProperty* property){
00141        icalcomponent_remove_property(imp, *property);
00142        icalproperty_free(*property);
00143         property->detach();        // set imp to null, it's free already.
00144 }
00145 int VComponent::count_properties(icalproperty_kind kind){
00146        return icalcomponent_count_properties(imp, kind);
00147 }
00148 
00149 /* Iterate through the properties */
00150 ICalProperty* VComponent::get_current_property(){
00151        icalproperty* t = icalcomponent_get_current_property(imp);
00152        return ((t != NULL) ? new ICalProperty(t) : NULL);
00153 }
00154 
00155 ICalProperty* VComponent::get_first_property(icalproperty_kind kind){
00156        icalproperty* t = icalcomponent_get_first_property(imp, kind);
00157        return ((t != NULL) ? new ICalProperty(t) : NULL);
00158 }
00159 
00160 ICalProperty* VComponent::get_next_property(icalproperty_kind kind){
00161        icalproperty* t = icalcomponent_get_next_property(imp, kind);
00162        return ((t != NULL) ? new ICalProperty(t) : NULL);
00163 }
00164 
00165 /* Working with components */ 
00166 /* Return the first VEVENT, VTODO or VJOURNAL sub-component if it is one of those types */
00167 VComponent* VComponent::get_inner(){
00168        return new VComponent(icalcomponent_get_inner(imp));
00169 }
00170 
00171 void VComponent::add_component(VComponent* child){
00172        icalcomponent_add_component(imp, *child);
00173 }
00174 void VComponent::remove_component(VComponent* child){
00175        icalcomponent_remove_component(imp, *child);
00176 }
00177 int VComponent::count_components(icalcomponent_kind kind){
00178        return        icalcomponent_count_components(imp, kind);
00179 }
00180 
00181 /* Iteration Routines. There are two forms of iterators, internal and
00182    external. The internal ones came first, and are almost completely
00183    sufficient, but they fail badly when you want to construct a loop that
00184    removes components from the container.
00185 */
00186 
00187 /* Iterate through components */
00188 VComponent* VComponent::get_current_component(){
00189        icalcomponent* t = icalcomponent_get_current_component(imp);
00190        return ((t != NULL) ? new VComponent(t) : NULL);
00191 }
00192 VComponent* VComponent::get_first_component(icalcomponent_kind kind){
00193        VComponent* result = NULL;
00194        icalcomponent* t = icalcomponent_get_first_component(imp, kind);
00195        if (t != NULL) {
00196               switch (kind) {
00197                      case ICAL_VALARM_COMPONENT:
00198                             result = new VAlarm(t);
00199                             break;
00200                      case ICAL_VCALENDAR_COMPONENT:
00201                             result = new VCalendar(t);
00202                             break;
00203                      case ICAL_VEVENT_COMPONENT:
00204                             result = new VEvent(t);
00205                             break;
00206                      case ICAL_VQUERY_COMPONENT:
00207                             result = new VQuery(t);
00208                             break;
00209                      case ICAL_VTODO_COMPONENT:
00210                             result = new VToDo(t);
00211                             break;
00212                         case ICAL_VAGENDA_COMPONENT:
00213                                 result = new VAgenda(t);
00214                                 break;
00215                      default:
00216                             result = new VComponent(t);
00217               }
00218        }
00219 
00220        return (result);
00221 }
00222 VComponent* VComponent::get_next_component(icalcomponent_kind kind){
00223        VComponent* result = NULL;
00224        icalcomponent* t = icalcomponent_get_next_component(imp, kind);
00225        if (t != NULL) {
00226               switch (kind) {
00227                      case ICAL_VALARM_COMPONENT:
00228                             result = new VAlarm(t);
00229                             break;
00230                      case ICAL_VCALENDAR_COMPONENT:
00231                             result = new VCalendar(t);
00232                             break;
00233                      case ICAL_VEVENT_COMPONENT:
00234                             result = new VEvent(t);
00235                             break;
00236                      case ICAL_VQUERY_COMPONENT:
00237                             result = new VQuery(t);
00238                             break;
00239                      case ICAL_VTODO_COMPONENT:
00240                             result = new VToDo(t);
00241                             break;
00242                         case ICAL_VAGENDA_COMPONENT:
00243                                 result = new VAgenda(t);
00244                                 break;
00245                      default:
00246                             result = new VComponent(t);
00247               }
00248        }
00249 
00250        return (result);
00251 }
00252 
00253 /* Using external iterators */
00254 icalcompiter VComponent::begin_component(icalcomponent_kind kind){
00255        return icalcomponent_begin_component(imp, kind);
00256 }
00257 icalcompiter VComponent::end_component(icalcomponent_kind kind){
00258        return icalcomponent_end_component(imp, kind);
00259 }
00260 VComponent* VComponent::next(icalcompiter* i){
00261        return (VComponent*)icalcompiter_next(i);
00262 }
00263 VComponent* VComponent::prev(icalcompiter* i){
00264        return (VComponent*)icalcompiter_prior(i);
00265 }
00266 VComponent* VComponent::current(icalcompiter* i){
00267        return (VComponent*)icalcompiter_deref(i);
00268 }
00269 
00270 /* Working with embedded error properties */
00271 int VComponent::count_errors(){
00272        return icalcomponent_count_errors(imp);
00273 }
00274 
00275 /* Remove all X-LIC-ERROR properties*/
00276 void VComponent::strip_errors(){
00277        icalcomponent_strip_errors(imp);
00278 }
00279 
00280 /* Convert some X-LIC-ERROR properties into RETURN-STATUS properties*/
00281 void VComponent::convert_errors(){
00282        icalcomponent_convert_errors(imp);
00283 }
00284 
00285 /* Kind conversion routines */
00286 icalcomponent_kind VComponent::string_to_kind(string str){
00287        return icalcomponent_string_to_kind(str);
00288 }
00289 string VComponent::kind_to_string(icalcomponent_kind kind){
00290        return (string)icalcomponent_kind_to_string(kind);
00291 }
00292 
00293 struct icaltimetype VComponent::get_dtstart(){
00294        return icalcomponent_get_dtstart(imp);
00295 }
00296 void VComponent::set_dtstart(struct icaltimetype v){
00297        icalcomponent_set_dtstart(imp, v);
00298 }
00299 
00300 /* For the icalcomponent routines only, dtend and duration are tied
00301    together. If you call the set routine for one and the other exists,
00302    the routine will calculate the change to the other. That is, if
00303    there is a DTEND and you call set_duration, the routine will modify
00304    DTEND to be the sum of DTSTART and the duration. If you call a get
00305    routine for one and the other exists, the routine will calculate
00306    the return value. If you call a set routine and neither exists, the
00307    routine will create the apcompriate comperty.
00308 */
00309 
00310 struct icaltimetype VComponent::get_dtend(){
00311        return icalcomponent_get_dtend(imp);
00312 }
00313 
00314 void VComponent::set_dtend(struct icaltimetype v){
00315        icalcomponent_set_dtend(imp, v);
00316 }
00317 
00318 struct icaltimetype VComponent::get_due(){
00319         return icalcomponent_get_due(imp);
00320 }
00321 void VComponent::set_due(struct icaltimetype v){
00322         icalcomponent_set_due(imp, v);
00323 }
00324 
00325 struct icaldurationtype VComponent::get_duration(){
00326        return icalcomponent_get_duration(imp);
00327 }
00328 void VComponent::set_duration(struct icaldurationtype v){
00329        icalcomponent_set_duration(imp, v);
00330 }
00331 
00332 icalproperty_method VComponent::get_method(){
00333        return icalcomponent_get_method(imp);
00334 }
00335 void VComponent::set_method(icalproperty_method method){
00336        icalcomponent_set_method(imp, method);
00337 }
00338 
00339 struct icaltimetype VComponent::get_dtstamp(){
00340        return icalcomponent_get_dtstamp(imp);
00341 }
00342 void VComponent::set_dtstamp(struct icaltimetype v){
00343        icalcomponent_set_dtstamp(imp, v);
00344 }
00345 
00346 string VComponent::get_summary(){
00347        return (string)icalcomponent_get_summary(imp);
00348 }
00349 void VComponent::set_summary(string v){
00350        icalcomponent_set_summary(imp, v);
00351 }
00352 
00353 string VComponent::get_location(){
00354         return (string)icalcomponent_get_location(imp);
00355 }
00356 void VComponent::set_location(string v){
00357         icalcomponent_set_location(imp, v);
00358 }
00359 
00360 
00361 string VComponent::get_description(){
00362         return (string)icalcomponent_get_description(imp);
00363 }
00364 void VComponent::set_description(string v){
00365         icalcomponent_set_description(imp, v);
00366 }
00367 string VComponent::get_comment(){
00368        return (string)icalcomponent_get_comment(imp);
00369 }
00370 void VComponent::set_comment(string v){
00371        icalcomponent_set_comment(imp, v);
00372 }
00373 
00374 string VComponent::get_uid(){
00375        return (string)icalcomponent_get_uid(imp);
00376 }
00377 void VComponent::set_uid(string v){
00378        icalcomponent_set_uid(imp, v);
00379 }
00380 
00381 string VComponent::get_relcalid(){
00382        return (string)icalcomponent_get_relcalid(imp);
00383 }
00384 void VComponent::set_relcalid(string v){
00385        icalcomponent_set_relcalid(imp, v);
00386 }
00387 
00388 struct icaltimetype VComponent::get_recurrenceid(){
00389        return icalcomponent_get_recurrenceid(imp);
00390 }
00391 void VComponent::set_recurrenceid(struct icaltimetype v){
00392        icalcomponent_set_recurrenceid(imp, v);
00393 }
00394 
00395 int VComponent::get_sequence(){
00396         return (int)icalcomponent_get_sequence(imp);
00397 }
00398 void VComponent::set_sequence(int v){
00399         icalcomponent_set_sequence(imp, v);
00400 }
00401 
00402 int VComponent::get_status(){
00403         return (int)icalcomponent_get_status(imp);
00404 }
00405 void VComponent::set_status(enum icalproperty_status v){
00406         icalcomponent_set_status(imp, v);
00407 }
00408 
00409 /* For VCOMPONENT: Return a reference to the first VEVENT, VTODO, or VJOURNAL */
00410 VComponent* VComponent::get_first_real_component(){
00411        return (VComponent*)icalcomponent_get_first_real_component(imp);
00412 }
00413 
00414 /* For VEVENT, VTODO, VJOURNAL and VTIMEZONE: report the start and end
00415    times of an event in UTC */
00416 struct icaltime_span VComponent::get_span(){
00417        return icalcomponent_get_span(imp);
00418 }
00419 
00420 int VComponent::recurrence_is_excluded( struct icaltimetype *dtstart,
00421                                        struct icaltimetype *recurtime){
00422        return  icalproperty_recurrence_is_excluded(imp, dtstart, recurtime);
00423 }
00424 
00425 
00426 /* Internal operations. They are private, and you should not be using them. */
00427 VComponent* VComponent::get_parent() {
00428        return new VComponent(icalcomponent_get_parent(imp));
00429 }
00430 void VComponent::set_parent(VComponent *parent){
00431        icalcomponent_set_parent(imp, *parent);
00432 }
00433 
00434 /* ignoreValue means remove properties even if the data doesn't match */
00435 bool VComponent::remove(VComponent& fromVC, bool ignoreValue){
00436 
00437     /* the two components must be the same kind */
00438     if (this->isa() != fromVC.isa()) return false;
00439 
00440     /* properties first */
00441     ICalPropertyTmpPtr propToBeRemoved;
00442     for (propToBeRemoved=fromVC.get_first_property(ICAL_ANY_PROPERTY); propToBeRemoved != NULL;
00443          propToBeRemoved=fromVC.get_next_property(ICAL_ANY_PROPERTY)) {
00444 
00445         /* loop through properties from this component */
00446         ICalPropertyTmpPtr next;
00447         ICalPropertyTmpPtr p;
00448         for (p=this->get_first_property(propToBeRemoved->isa()); p != NULL; p=next) {
00449             next = this->get_next_property(propToBeRemoved->isa());
00450             if (ignoreValue)
00451                  this->remove_property(p);
00452             else {
00453                  if (*p == *propToBeRemoved) {
00454                      this->remove_property(p);
00455                      break;
00456                  }
00457             }
00458         }
00459     }
00460 
00461     /* components next - should remove by UID */
00462     VComponentTmpPtr comp;
00463     for (comp=fromVC.get_first_component(ICAL_ANY_COMPONENT); comp != NULL;
00464          comp=fromVC.get_next_component(ICAL_ANY_COMPONENT)) {
00465         const char* fromCompUid = comp->get_uid();
00466         VComponentTmpPtr c;
00467         for (c=this->get_first_component(comp->isa()); c != NULL;
00468              c=this->get_next_component(comp->isa())) {
00469             const char* thisCompUid = c->get_uid();
00470             if (strcmp(fromCompUid, thisCompUid) == 0) {
00471                 // recursively go down the components
00472                 c->remove(*comp, ignoreValue);
00473                     // if all properties are removed and there is no sub-components, then
00474                     // remove this compoent
00475                     if ((c->count_properties(ICAL_ANY_PROPERTY) == 0) &&
00476                         (c->count_components(ICAL_ANY_COMPONENT) == 0)) {
00477                         this->remove_component(c);
00478                     }
00479                 break;
00480                 }
00481             }
00482     }
00483     
00484     return true;
00485 }
00486 /* removeMissing == true: remove properties that are missing from fromC */
00487 /* todo: only change the first occurrence of the property */
00488 /* todo: removeMissing is not implemented */
00489 bool VComponent::update(VComponent& fromC, bool removeMissing){
00490 
00491     /* make sure they are the same kind */
00492     if (this->isa() != fromC.isa()) return false;
00493 
00494     /* property first */
00495     ICalPropertyTmpPtr prop;
00496     for (prop=fromC.get_first_property(ICAL_ANY_PROPERTY); prop != NULL;
00497         prop=fromC.get_next_property(ICAL_ANY_PROPERTY)) {
00498         ICalPropertyTmpPtr thisProp;
00499        thisProp = this->get_first_property(prop->isa());
00500        if (thisProp == NULL) {
00501             thisProp = new ICalProperty(prop->isa());
00502             this->add_property(thisProp);
00503         }
00504         ICalValue *value = new ICalValue(*(prop->get_value())); // clone the value
00505         thisProp->set_value(*value);
00506     }
00507 
00508     /* recursively updating sub-components */
00509     VComponentTmpPtr comp;
00510     for (comp=fromC.get_first_component(ICAL_ANY_COMPONENT); comp != NULL;
00511          comp=fromC.get_next_component(ICAL_ANY_COMPONENT)) {
00512         VComponentTmpPtr thisComp;
00513         thisComp = this->get_first_component(comp->isa());
00514         if (thisComp == NULL) {
00515             thisComp = new VComponent(comp->isa());
00516             this->add_component(thisComp);
00517         }
00518         bool err = thisComp->update(*comp, removeMissing);
00519         if (!err) return false;
00520     }
00521     return true;
00522 }
00523 /* add components and property. recursively goes down child components */
00524 bool VComponent::add(VComponent& fromC){
00525        /* make sure the kind are the same */
00526        if (this->isa() != fromC.isa()) return false;
00527 
00528        /* properties first */
00529     ICalPropertyTmpPtr prop;
00530        for (prop=fromC.get_first_property(ICAL_ANY_PROPERTY); prop != NULL;
00531                prop=fromC.get_next_property(ICAL_ANY_PROPERTY)) {
00532               /* clone another property */
00533               ICalProperty *p = new ICalProperty(*prop);
00534               add_property(p);
00535        }
00536 
00537        /* sub-components next */
00538        bool err = false;
00539     VComponentTmpPtr comp;
00540        for (comp=fromC.get_first_component(ICAL_ANY_COMPONENT); comp != NULL;
00541                comp=fromC.get_next_component(ICAL_ANY_COMPONENT)) {
00542               VComponent *c = new VComponent(comp->isa());
00543               err = c->add(*comp);
00544               add_component(c);
00545        }
00546 
00547        return true;
00548 }
00549 
00550 VCalendar::VCalendar() : VComponent(icalcomponent_new_vcalendar()){
00551 }
00552 VCalendar::VCalendar(const VCalendar& v) : VComponent(v) {}
00553 VCalendar& VCalendar::operator=(const VCalendar& v){
00554        if (this == &v) return *this;
00555        VComponent::operator=(v);
00556 
00557        return *this;
00558 }
00559 VCalendar::~VCalendar(){}
00560 
00561 VCalendar::VCalendar(icalcomponent* v) : VComponent(v){}
00562 VCalendar::VCalendar(string str) : VComponent(str){}
00563 
00564 
00565 /* VEvent */
00566 
00567 VEvent::VEvent() : VComponent(icalcomponent_new_vevent()){}
00568 VEvent::VEvent(const VEvent& v) : VComponent(v) {}
00569 VEvent& VEvent::operator=(const VEvent& v){
00570        if (this == &v) return *this;
00571        VComponent::operator=(v);
00572 
00573        return *this;
00574 }
00575 VEvent::~VEvent(){}
00576 
00577 VEvent::VEvent(icalcomponent* v) : VComponent(v){}
00578 VEvent::VEvent(string str) : VComponent(str){}
00579 
00580 
00581 /* VTodo */
00582 
00583 VToDo::VToDo() : VComponent(icalcomponent_new_vtodo()){}
00584 VToDo::VToDo(const VToDo& v) : VComponent(v) {}
00585 VToDo& VToDo::operator=(const VToDo& v){
00586        if (this == &v) return *this;
00587        VComponent::operator=(v);
00588 
00589        return *this;
00590 }
00591 VToDo::~VToDo(){}
00592 
00593 VToDo::VToDo(icalcomponent* v) : VComponent(v){}
00594 VToDo::VToDo(string str) : VComponent(str){}
00595 
00596 
00597 /* VAgenda */
00598 
00599 VAgenda::VAgenda() : VComponent(icalcomponent_new_vagenda()){}
00600 VAgenda::VAgenda(const VAgenda& v) : VComponent(v) {}
00601 VAgenda& VAgenda::operator=(const VAgenda& v){
00602         if (this == &v) return *this;
00603         VComponent::operator=(v);
00604 
00605         return *this;
00606 }
00607 VAgenda::~VAgenda(){}
00608 
00609 VAgenda::VAgenda(icalcomponent* v) : VComponent(v){}
00610 VAgenda::VAgenda(string str) : VComponent(str){}
00611 
00612 
00613 /* VQuery */
00614 
00615 VQuery::VQuery() : VComponent(icalcomponent_new_vquery()){}
00616 VQuery::VQuery(const VQuery& v) : VComponent(v) {}
00617 VQuery& VQuery::operator=(const VQuery& v){
00618        if (this == &v) return *this;
00619        VComponent::operator=(v);
00620 
00621        return *this;
00622 }
00623 VQuery::~VQuery(){}
00624 
00625 VQuery::VQuery(icalcomponent* v) : VComponent(v){}
00626 VQuery::VQuery(string str) : VComponent(str){}
00627 
00628 
00629 /* VJournal */
00630 
00631 VJournal::VJournal() : VComponent(icalcomponent_new_vjournal()){}
00632 VJournal::VJournal(const VJournal& v) : VComponent(v) {}
00633 VJournal& VJournal::operator=(const VJournal& v){
00634        if (this == &v) return *this;
00635        VComponent::operator=(v);
00636 
00637        return *this;
00638 }
00639 VJournal::~VJournal(){}
00640 
00641 VJournal::VJournal(icalcomponent* v) : VComponent(v){}
00642 VJournal::VJournal(string str) : VComponent(str){}
00643 
00644 
00645 /* VAlarm */
00646 
00647 VAlarm::VAlarm() : VComponent(icalcomponent_new_valarm()){}
00648 VAlarm::VAlarm(const VAlarm& v) : VComponent(v) {}
00649 VAlarm& VAlarm::operator=(const VAlarm& v){
00650        if (this == &v) return *this;
00651        VComponent::operator=(v);
00652 
00653        return *this;
00654 }
00655 VAlarm::~VAlarm(){}
00656 
00657 VAlarm::VAlarm(icalcomponent* v) : VComponent(v){}
00658 VAlarm::VAlarm(string str) : VComponent(str){}
00659 
00660 icalrequeststatus
00661 VAlarm::getTriggerTime(VComponent &c, struct icaltriggertype *tr)
00662 {
00663   struct icaltimetype tt;
00664   ICalParameter *related_param;
00665 
00666   ICalPropertyTmpPtr trigger_prop = this->get_first_property(ICAL_TRIGGER_PROPERTY);
00667 
00668   // all VALARMs must have a TRIGGER
00669   if (trigger_prop == NULL)  
00670     return ICAL_3_1_INVPROPVAL_STATUS; 
00671 
00672   *tr = trigger_prop->get_trigger();
00673 
00674   tt = icaltime_null_time();
00675 
00676   if (icaltime_is_null_time(tr->time)) {
00677 
00678     // relative time trigger
00679 
00680     // TRIGGER;RELATED=END:P5M 5 minutes after END
00681     // TRIGGER;RELATED=START:-P15M 15 minutes before START
00682     // get RELATED parameter
00683 
00684     related_param = trigger_prop->get_first_parameter(ICAL_RELATED_PARAMETER);
00685 
00686     if (related_param && related_param->is_valid()) {
00687 
00688         // get RELATED parameter value
00689         icalparameter_related related = related_param->get_related();
00690 
00691         if(related) {
00692             switch(related) {
00693                 case ICAL_RELATED_END:
00694                     if (c.isa() == ICAL_VEVENT_COMPONENT) {
00695                         tt = c.get_dtend();
00696 
00697                      // If a recurrenceid exists, use that to calculate the
00698                      // dtend from the dtstart.
00699                      struct icaltimetype recur_time = c.get_recurrenceid();
00700                      if (!(icaltime_is_null_time(recur_time))) {
00701                          struct icaldurationtype dur = icaltime_subtract(c.get_dtstart(), tt);
00702                          tt = icaltime_add(recur_time, dur);
00703                       } 
00704                   }  
00705                     else if (c.isa() == ICAL_VTODO_COMPONENT) {
00706                         tt = c.get_due();
00707                      struct icaltimetype recur_time = c.get_recurrenceid();
00708                      if (!(icaltime_is_null_time(recur_time))) {
00709                          tt = recur_time;
00710                      }
00711                   }
00712                     // @@@ TODO: if not DTEND or DUE, then DTSTART and DURATION must be present
00713                 break;
00714                 case ICAL_RELATED_START:
00715                 case ICAL_RELATED_X:
00716                 case ICAL_RELATED_NONE:
00717                 default:
00718                     tt = c.get_dtstart();
00719                     struct icaltimetype recur_time = c.get_recurrenceid();
00720                     if (!(icaltime_is_null_time(recur_time))) {
00721                         tt = recur_time;
00722                     }
00723                 break;
00724             }
00725 
00726         }
00727     }
00728     else { // no RELATED explicity specified, the default is 
00729            // relative to the start of an event or to-do, rfc2445
00730         // if no RELATED, we are forced to use dtstart for VEVENT,
00731         // due for VTODO to calculate trigger time. 
00732        // If a recur time exists, use that. Recur time trumps dtstart or due.
00733         struct icaltimetype recur_time = c.get_recurrenceid();
00734        if (!(icaltime_is_null_time(recur_time))) {
00735            tt = recur_time;
00736        }
00737        else if (c.isa() == ICAL_VEVENT_COMPONENT)
00738             tt = c.get_dtstart();
00739         else if (c.isa() == ICAL_VTODO_COMPONENT)
00740             tt = c.get_due();
00741     }
00742 
00743     // malformed? encapsulating VEVENT or VTODO MUST have DTSTART/DTEND 
00744     if(icaltime_is_null_time(tt))
00745       return ICAL_3_1_INVPROPVAL_STATUS;;
00746 
00747     // now offset using tr.duration
00748     tr->time = icaltime_add(tt, tr->duration);
00749   }
00750   // else absolute time trigger
00751 
00752   return ICAL_2_0_SUCCESS_STATUS;
00753 }
00754 
00755 
00756 /* VFreeBusy */
00757 
00758 VFreeBusy::VFreeBusy() : VComponent(icalcomponent_new_vfreebusy()){}
00759 VFreeBusy::VFreeBusy(const VFreeBusy& v) : VComponent(v) {}
00760 VFreeBusy& VFreeBusy::operator=(const VFreeBusy& v){
00761        if (this == &v) return *this;
00762        VComponent::operator=(v);
00763 
00764        return *this;
00765 }
00766 VFreeBusy::~VFreeBusy(){}
00767 
00768 VFreeBusy::VFreeBusy(icalcomponent* v) : VComponent(v){}
00769 VFreeBusy::VFreeBusy(string str) : VComponent(str){}
00770 
00771 
00772 /* VTimezone */
00773 
00774 VTimezone::VTimezone() : VComponent(icalcomponent_new_vtimezone()){}
00775 VTimezone::VTimezone(const VTimezone& v) : VComponent(v) {}
00776 VTimezone& VTimezone::operator=(const VTimezone& v){
00777        if (this == &v) return *this;
00778        VComponent::operator=(v);
00779 
00780        return *this;
00781 }
00782 VTimezone::~VTimezone(){}
00783 
00784 VTimezone::VTimezone(icalcomponent* v) : VComponent(v){}
00785 VTimezone::VTimezone(string str) : VComponent(str){}
00786 
00787 
00788 /* XStandard */
00789 
00790 XStandard::XStandard() : VComponent(icalcomponent_new_xstandard()){}
00791 XStandard::XStandard(const XStandard& v) : VComponent(v) {}
00792 XStandard& XStandard::operator=(const XStandard& v){
00793        if (this == &v) return *this;
00794        VComponent::operator=(v);
00795 
00796        return *this;
00797 }
00798 XStandard::~XStandard(){}
00799 
00800 XStandard::XStandard(icalcomponent* v) : VComponent(v){}
00801 XStandard::XStandard(string str) : VComponent(str){}
00802 
00803 
00804 /* XDaylight */
00805 
00806 XDaylight::XDaylight() : VComponent(icalcomponent_new_xdaylight()){}
00807 XDaylight::XDaylight(const XDaylight& v) : VComponent(v) {}
00808 XDaylight& XDaylight::operator=(const XDaylight& v){
00809        if (this == &v) return *this;
00810        VComponent::operator=(v);
00811 
00812        return *this;
00813 }
00814 XDaylight::~XDaylight(){}
00815 
00816 XDaylight::XDaylight(icalcomponent* v) : VComponent(v){}
00817 XDaylight::XDaylight(string str) : VComponent(str){}