evolution-3.6.4/calendar/gui/e-meeting-attendee.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-meeting-attendee.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-meeting-attendee.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
   1 /*
   2  * This program is free software; you can redistribute it and/or
   3  * modify it under the terms of the GNU Lesser General Public
   4  * License as published by the Free Software Foundation; either
   5  * version 2 of the License, or (at your option) version 3.
   6  *
   7  * This program is distributed in the hope that it will be useful,
   8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  10  * Lesser General Public License for more details.
  11  *
  12  * You should have received a copy of the GNU Lesser General Public
  13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
  14  *
  15  *
  16  * Authors:
  17  *		JP Rosevear <jpr@ximian.com>
  18  *
  19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
  20  *
  21  */
  22 
  23 #ifdef HAVE_CONFIG_H
  24 #include <config.h>
  25 #endif
  26 
  27 #include <stdlib.h>
  28 #include <gtk/gtk.h>
  29 #include "e-meeting-utils.h"
  30 #include "e-meeting-attendee.h"
  31 
  32 #define E_MEETING_ATTENDEE_GET_PRIVATE(obj) \
  33 	(G_TYPE_INSTANCE_GET_PRIVATE \
  34 	((obj), E_TYPE_MEETING_ATTENDEE, EMeetingAttendeePrivate))
  35 
  36 struct _EMeetingAttendeePrivate {
  37 	gchar *address;
  38 	gchar *member;
  39 	gchar *fburi;
  40 
  41 	icalparameter_cutype cutype;
  42 	icalparameter_role role;
  43 
  44 	gboolean rsvp;
  45 
  46 	gchar *delto;
  47 	gchar *delfrom;
  48 
  49 	icalparameter_partstat status;
  50 
  51 	gchar *sentby;
  52 	gchar *cn;
  53 	gchar *language;
  54 
  55 	EMeetingAttendeeEditLevel edit_level;
  56 
  57 	gboolean has_calendar_info;
  58 
  59 	GArray *busy_periods;
  60 	gboolean busy_periods_sorted;
  61 
  62 	EMeetingTime busy_periods_start;
  63 	EMeetingTime busy_periods_end;
  64 	gboolean start_busy_range_set;
  65 	gboolean end_busy_range_set;
  66 
  67 	gint longest_period_in_days;
  68 };
  69 
  70 enum {
  71 	CHANGED,
  72 	LAST_SIGNAL
  73 };
  74 static guint signals[LAST_SIGNAL];
  75 
  76 static void e_meeting_attendee_finalize	(GObject *obj);
  77 
  78 G_DEFINE_TYPE (EMeetingAttendee, e_meeting_attendee, G_TYPE_OBJECT)
  79 
  80 static gchar *
  81 string_test (gchar *string)
  82 {
  83 	return string != NULL ? string : g_strdup ("");
  84 }
  85 
  86 static gboolean
  87 string_is_set (gchar *string)
  88 {
  89 	if (string != NULL && *string != '\0')
  90 		return TRUE;
  91 
  92 	return FALSE;
  93 }
  94 
  95 static void
  96 busy_periods_array_clear_func (gpointer data)
  97 {
  98 	EMeetingFreeBusyPeriod *period = (EMeetingFreeBusyPeriod *) data;
  99 
 100 	/* We're expected to clear the data segment,
 101 	 * but not deallocate the segment itself. The
 102 	 * XFB data possibly attached to the
 103 	 * EMeetingFreeBusyPeriod requires special
 104 	 * care when removing elements from the GArray
 105 	 */
 106 	e_meeting_xfb_data_clear (&(period->xfb));
 107 }
 108 
 109 static void
 110 notify_changed (EMeetingAttendee *ia)
 111 {
 112 	g_signal_emit_by_name (ia, "changed");
 113 }
 114 
 115 static void
 116 e_meeting_attendee_finalize (GObject *object)
 117 {
 118 	EMeetingAttendeePrivate *priv;
 119 
 120 	priv = E_MEETING_ATTENDEE_GET_PRIVATE (object);
 121 
 122 	g_free (priv->address);
 123 	g_free (priv->member);
 124 	g_free (priv->fburi);
 125 
 126 	g_free (priv->delto);
 127 	g_free (priv->delfrom);
 128 
 129 	g_free (priv->sentby);
 130 	g_free (priv->cn);
 131 	g_free (priv->language);
 132 
 133 	g_array_free (priv->busy_periods, TRUE);
 134 
 135 	/* Chain up to parent's finalize() method. */
 136 	G_OBJECT_CLASS (e_meeting_attendee_parent_class)->finalize (object);
 137 }
 138 
 139 static void
 140 e_meeting_attendee_class_init (EMeetingAttendeeClass *class)
 141 {
 142 	GObjectClass *object_class;
 143 
 144 	g_type_class_add_private (class, sizeof (EMeetingAttendeePrivate));
 145 
 146 	object_class = G_OBJECT_CLASS (class);
 147 	object_class->finalize = e_meeting_attendee_finalize;
 148 
 149 	signals[CHANGED] = g_signal_new (
 150 		"changed",
 151 		G_TYPE_FROM_CLASS (class),
 152 		G_SIGNAL_RUN_FIRST,
 153 		G_STRUCT_OFFSET (EMeetingAttendeeClass, changed),
 154 		NULL, NULL,
 155 		g_cclosure_marshal_VOID__VOID,
 156 		G_TYPE_NONE, 0);
 157 }
 158 
 159 static void
 160 e_meeting_attendee_init (EMeetingAttendee *ia)
 161 {
 162 	ia->priv = E_MEETING_ATTENDEE_GET_PRIVATE (ia);
 163 
 164 	ia->priv->address = string_test (NULL);
 165 	ia->priv->member = string_test (NULL);
 166 
 167 	ia->priv->cutype = ICAL_CUTYPE_NONE;
 168 	ia->priv->role = ICAL_ROLE_NONE;
 169 
 170 	ia->priv->rsvp = FALSE;
 171 
 172 	ia->priv->delto = string_test (NULL);
 173 	ia->priv->delfrom = string_test (NULL);
 174 
 175 	ia->priv->status = ICAL_PARTSTAT_NONE;
 176 
 177 	ia->priv->sentby = string_test (NULL);
 178 	ia->priv->cn = string_test (NULL);
 179 	ia->priv->language = string_test (NULL);
 180 
 181 	ia->priv->edit_level = E_MEETING_ATTENDEE_EDIT_FULL;
 182 	ia->priv->has_calendar_info = FALSE;
 183 
 184 	ia->priv->busy_periods = g_array_new (FALSE, FALSE, sizeof (EMeetingFreeBusyPeriod));
 185 	g_array_set_clear_func (ia->priv->busy_periods, busy_periods_array_clear_func);
 186 	ia->priv->busy_periods_sorted = FALSE;
 187 
 188 	g_date_clear (&ia->priv->busy_periods_start.date, 1);
 189 	ia->priv->busy_periods_start.hour = 0;
 190 	ia->priv->busy_periods_start.minute = 0;
 191 
 192 	g_date_clear (&ia->priv->busy_periods_end.date, 1);
 193 	ia->priv->busy_periods_end.hour = 0;
 194 	ia->priv->busy_periods_end.minute = 0;
 195 
 196 	ia->priv->start_busy_range_set = FALSE;
 197 	ia->priv->end_busy_range_set = FALSE;
 198 
 199 	ia->priv->longest_period_in_days = 0;
 200 }
 201 
 202 GObject *
 203 e_meeting_attendee_new (void)
 204 {
 205 	return g_object_new (E_TYPE_MEETING_ATTENDEE, NULL);
 206 }
 207 
 208 GObject *
 209 e_meeting_attendee_new_from_e_cal_component_attendee (ECalComponentAttendee *ca)
 210 {
 211 	EMeetingAttendee *ia;
 212 
 213 	ia = E_MEETING_ATTENDEE (g_object_new (E_TYPE_MEETING_ATTENDEE, NULL));
 214 
 215 	e_meeting_attendee_set_address (ia, g_strdup (ca->value));
 216 	e_meeting_attendee_set_member (ia, g_strdup (ca->member));
 217 	e_meeting_attendee_set_cutype (ia, ca->cutype);
 218 	e_meeting_attendee_set_role (ia, ca->role);
 219 	e_meeting_attendee_set_status (ia, ca->status);
 220 	e_meeting_attendee_set_rsvp (ia, ca->rsvp);
 221 	e_meeting_attendee_set_delto (ia, g_strdup (ca->delto));
 222 	e_meeting_attendee_set_delfrom (ia, g_strdup (ca->delfrom));
 223 	e_meeting_attendee_set_sentby (ia, g_strdup (ca->sentby));
 224 	e_meeting_attendee_set_cn (ia, g_strdup (ca->cn));
 225 	e_meeting_attendee_set_language (ia, g_strdup (ca->language));
 226 
 227 	return G_OBJECT (ia);
 228 }
 229 
 230 ECalComponentAttendee *
 231 e_meeting_attendee_as_e_cal_component_attendee (EMeetingAttendee *ia)
 232 {
 233 	EMeetingAttendeePrivate *priv;
 234 	ECalComponentAttendee *ca;
 235 
 236 	priv = ia->priv;
 237 
 238 	ca = g_new0 (ECalComponentAttendee, 1);
 239 
 240 	ca->value = priv->address;
 241 	ca->member = string_is_set (priv->member) ? priv->member : NULL;
 242 	ca->cutype= priv->cutype;
 243 	ca->role = priv->role;
 244 	ca->status = priv->status;
 245 	ca->rsvp = priv->rsvp;
 246 	ca->delto = string_is_set (priv->delto) ? priv->delto : NULL;
 247 	ca->delfrom = string_is_set (priv->delfrom) ? priv->delfrom : NULL;
 248 	ca->sentby = string_is_set (priv->sentby) ? priv->sentby : NULL;
 249 	ca->cn = string_is_set (priv->cn) ? priv->cn : NULL;
 250 	ca->language = string_is_set (priv->language) ? priv->language : NULL;
 251 
 252 	return ca;
 253 }
 254 
 255 const gchar *
 256 e_meeting_attendee_get_fburi (EMeetingAttendee *ia)
 257 {
 258 	EMeetingAttendeePrivate *priv;
 259 
 260 	priv = ia->priv;
 261 
 262 	return priv->fburi;
 263 }
 264 
 265 void
 266 e_meeting_attendee_set_fburi (EMeetingAttendee *ia,
 267                               gchar *fburi)
 268 {
 269 	EMeetingAttendeePrivate *priv;
 270 
 271 	priv = ia->priv;
 272 
 273 	if (priv->fburi != NULL)
 274 		g_free (priv->fburi);
 275 
 276 	priv->fburi = string_test (fburi);
 277 
 278 	notify_changed (ia);
 279 }
 280 
 281 const gchar *
 282 e_meeting_attendee_get_address (EMeetingAttendee *ia)
 283 {
 284 	EMeetingAttendeePrivate *priv;
 285 
 286 	priv = ia->priv;
 287 
 288 	return priv->address;
 289 }
 290 
 291 void
 292 e_meeting_attendee_set_address (EMeetingAttendee *ia,
 293                                 gchar *address)
 294 {
 295 	EMeetingAttendeePrivate *priv;
 296 
 297 	priv = ia->priv;
 298 
 299 	if (priv->address != NULL)
 300 		g_free (priv->address);
 301 
 302 	priv->address = string_test (address);
 303 
 304 	notify_changed (ia);
 305 }
 306 
 307 gboolean
 308 e_meeting_attendee_is_set_address (EMeetingAttendee *ia)
 309 {
 310 	EMeetingAttendeePrivate *priv;
 311 
 312 	priv = ia->priv;
 313 
 314 	return string_is_set (priv->address);
 315 }
 316 
 317 const gchar *
 318 e_meeting_attendee_get_member (EMeetingAttendee *ia)
 319 {
 320 	EMeetingAttendeePrivate *priv;
 321 
 322 	priv = ia->priv;
 323 
 324 	return priv->member;
 325 }
 326 
 327 void
 328 e_meeting_attendee_set_member (EMeetingAttendee *ia,
 329                                gchar *member)
 330 {
 331 	EMeetingAttendeePrivate *priv;
 332 
 333 	priv = ia->priv;
 334 
 335 	if (priv->member != NULL)
 336 		g_free (priv->member);
 337 
 338 	priv->member = string_test (member);
 339 
 340 	notify_changed (ia);
 341 }
 342 
 343 gboolean
 344 e_meeting_attendee_is_set_member (EMeetingAttendee *ia)
 345 {
 346 	EMeetingAttendeePrivate *priv;
 347 
 348 	priv = ia->priv;
 349 
 350 	return string_is_set (priv->member);
 351 }
 352 
 353 icalparameter_cutype
 354 e_meeting_attendee_get_cutype (EMeetingAttendee *ia)
 355 {
 356 	EMeetingAttendeePrivate *priv;
 357 
 358 	priv = ia->priv;
 359 
 360 	return priv->cutype;
 361 }
 362 
 363 void
 364 e_meeting_attendee_set_cutype (EMeetingAttendee *ia,
 365                                icalparameter_cutype cutype)
 366 {
 367 	EMeetingAttendeePrivate *priv;
 368 
 369 	priv = ia->priv;
 370 
 371 	priv->cutype = cutype;
 372 
 373 	notify_changed (ia);
 374 }
 375 
 376 icalparameter_role
 377 e_meeting_attendee_get_role (EMeetingAttendee *ia)
 378 {
 379 	EMeetingAttendeePrivate *priv;
 380 
 381 	priv = ia->priv;
 382 
 383 	return priv->role;
 384 }
 385 
 386 void
 387 e_meeting_attendee_set_role (EMeetingAttendee *ia,
 388                              icalparameter_role role)
 389 {
 390 	EMeetingAttendeePrivate *priv;
 391 
 392 	priv = ia->priv;
 393 
 394 	priv->role = role;
 395 
 396 	notify_changed (ia);
 397 }
 398 
 399 gboolean
 400 e_meeting_attendee_get_rsvp (EMeetingAttendee *ia)
 401 {
 402 	EMeetingAttendeePrivate *priv;
 403 
 404 	priv = ia->priv;
 405 
 406 	return priv->rsvp;
 407 }
 408 
 409 void
 410 e_meeting_attendee_set_rsvp (EMeetingAttendee *ia,
 411                              gboolean rsvp)
 412 {
 413 	EMeetingAttendeePrivate *priv;
 414 
 415 	priv = ia->priv;
 416 
 417 	priv->rsvp = rsvp;
 418 
 419 	notify_changed (ia);
 420 }
 421 
 422 const gchar *
 423 e_meeting_attendee_get_delto (EMeetingAttendee *ia)
 424 {
 425 	EMeetingAttendeePrivate *priv;
 426 
 427 	priv = ia->priv;
 428 
 429 	return priv->delto;
 430 }
 431 
 432 void
 433 e_meeting_attendee_set_delto (EMeetingAttendee *ia,
 434                               gchar *delto)
 435 {
 436 	EMeetingAttendeePrivate *priv;
 437 
 438 	priv = ia->priv;
 439 
 440 	if (priv->delto != NULL)
 441 		g_free (priv->delto);
 442 
 443 	priv->delto = string_test (delto);
 444 
 445 	notify_changed (ia);
 446 }
 447 
 448 gboolean
 449 e_meeting_attendee_is_set_delto (EMeetingAttendee *ia)
 450 {
 451 	EMeetingAttendeePrivate *priv;
 452 
 453 	priv = ia->priv;
 454 
 455 	return string_is_set (priv->delto);
 456 }
 457 
 458 const gchar *
 459 e_meeting_attendee_get_delfrom (EMeetingAttendee *ia)
 460 {
 461 	EMeetingAttendeePrivate *priv;
 462 
 463 	priv = ia->priv;
 464 
 465 	return priv->delfrom;
 466 }
 467 
 468 void
 469 e_meeting_attendee_set_delfrom (EMeetingAttendee *ia,
 470                                 gchar *delfrom)
 471 {
 472 	EMeetingAttendeePrivate *priv;
 473 
 474 	priv = ia->priv;
 475 
 476 	if (priv->delfrom != NULL)
 477 		g_free (priv->delfrom);
 478 
 479 	priv->delfrom = string_test (delfrom);
 480 
 481 	notify_changed (ia);
 482 }
 483 
 484 gboolean
 485 e_meeting_attendee_is_set_delfrom (EMeetingAttendee *ia)
 486 {
 487 	EMeetingAttendeePrivate *priv;
 488 
 489 	priv = ia->priv;
 490 
 491 	return string_is_set (priv->delfrom);
 492 }
 493 
 494 icalparameter_partstat
 495 e_meeting_attendee_get_status (EMeetingAttendee *ia)
 496 {
 497 	EMeetingAttendeePrivate *priv;
 498 
 499 	priv = ia->priv;
 500 
 501 	return priv->status;
 502 }
 503 
 504 void
 505 e_meeting_attendee_set_status (EMeetingAttendee *ia,
 506                                icalparameter_partstat status)
 507 {
 508 	EMeetingAttendeePrivate *priv;
 509 
 510 	priv = ia->priv;
 511 
 512 	priv->status = status;
 513 
 514 	notify_changed (ia);
 515 }
 516 
 517 const gchar *
 518 e_meeting_attendee_get_sentby (EMeetingAttendee *ia)
 519 {
 520 	EMeetingAttendeePrivate *priv;
 521 
 522 	priv = ia->priv;
 523 
 524 	return priv->sentby;
 525 }
 526 
 527 void
 528 e_meeting_attendee_set_sentby (EMeetingAttendee *ia,
 529                                gchar *sentby)
 530 {
 531 	EMeetingAttendeePrivate *priv;
 532 
 533 	priv = ia->priv;
 534 
 535 	if (priv->sentby != NULL)
 536 		g_free (priv->sentby);
 537 
 538 	priv->sentby = string_test (sentby);
 539 
 540 	notify_changed (ia);
 541 }
 542 
 543 gboolean
 544 e_meeting_attendee_is_set_sentby (EMeetingAttendee *ia)
 545 {
 546 	EMeetingAttendeePrivate *priv;
 547 
 548 	priv = ia->priv;
 549 
 550 	return string_is_set (priv->sentby);
 551 }
 552 
 553 const gchar *
 554 e_meeting_attendee_get_cn (EMeetingAttendee *ia)
 555 {
 556 	EMeetingAttendeePrivate *priv;
 557 
 558 	priv = ia->priv;
 559 
 560 	return priv->cn;
 561 }
 562 
 563 void
 564 e_meeting_attendee_set_cn (EMeetingAttendee *ia,
 565                            gchar *cn)
 566 {
 567 	EMeetingAttendeePrivate *priv;
 568 
 569 	priv = ia->priv;
 570 
 571 	if (priv->cn != NULL)
 572 		g_free (priv->cn);
 573 
 574 	priv->cn = string_test (cn);
 575 
 576 	notify_changed (ia);
 577 }
 578 
 579 gboolean
 580 e_meeting_attendee_is_set_cn (EMeetingAttendee *ia)
 581 {
 582 	EMeetingAttendeePrivate *priv;
 583 
 584 	priv = ia->priv;
 585 
 586 	return string_is_set (priv->cn);
 587 }
 588 
 589 const gchar *
 590 e_meeting_attendee_get_language (EMeetingAttendee *ia)
 591 {
 592 	EMeetingAttendeePrivate *priv;
 593 
 594 	priv = ia->priv;
 595 
 596 	return priv->language;
 597 }
 598 
 599 void
 600 e_meeting_attendee_set_language (EMeetingAttendee *ia,
 601                                  gchar *language)
 602 {
 603 	EMeetingAttendeePrivate *priv;
 604 
 605 	priv = ia->priv;
 606 
 607 	if (priv->language != NULL)
 608 		g_free (priv->language);
 609 
 610 	priv->language = string_test (language);
 611 
 612 	notify_changed (ia);
 613 }
 614 
 615 gboolean
 616 e_meeting_attendee_is_set_language (EMeetingAttendee *ia)
 617 {
 618 	EMeetingAttendeePrivate *priv;
 619 
 620 	priv = ia->priv;
 621 
 622 	return string_is_set (priv->language);
 623 }
 624 
 625 EMeetingAttendeeType
 626 e_meeting_attendee_get_atype (EMeetingAttendee *ia)
 627 {
 628 	EMeetingAttendeePrivate *priv;
 629 
 630 	priv = ia->priv;
 631 
 632 	if (priv->cutype == ICAL_CUTYPE_ROOM
 633 	    || priv->cutype == ICAL_CUTYPE_RESOURCE)
 634 		return E_MEETING_ATTENDEE_RESOURCE;
 635 
 636 	if (priv->role == ICAL_ROLE_CHAIR
 637 	    || priv->role == ICAL_ROLE_REQPARTICIPANT)
 638 		return E_MEETING_ATTENDEE_REQUIRED_PERSON;
 639 
 640 	return E_MEETING_ATTENDEE_OPTIONAL_PERSON;
 641 }
 642 
 643 EMeetingAttendeeEditLevel
 644 e_meeting_attendee_get_edit_level (EMeetingAttendee *ia)
 645 {
 646 	EMeetingAttendeePrivate *priv;
 647 
 648 	g_return_val_if_fail (ia != NULL, E_MEETING_ATTENDEE_EDIT_NONE);
 649 	g_return_val_if_fail (E_IS_MEETING_ATTENDEE (ia), E_MEETING_ATTENDEE_EDIT_NONE);
 650 
 651 	priv = ia->priv;
 652 
 653 	return priv->edit_level;
 654 }
 655 
 656 void
 657 e_meeting_attendee_set_edit_level (EMeetingAttendee *ia,
 658                                    EMeetingAttendeeEditLevel level)
 659 {
 660 	EMeetingAttendeePrivate *priv;
 661 
 662 	g_return_if_fail (ia != NULL);
 663 	g_return_if_fail (E_IS_MEETING_ATTENDEE (ia));
 664 
 665 	priv = ia->priv;
 666 
 667 	priv->edit_level = level;
 668 }
 669 
 670 static gint
 671 compare_times (EMeetingTime *time1,
 672                EMeetingTime *time2)
 673 {
 674 	gint day_comparison;
 675 
 676 	day_comparison = g_date_compare (
 677 		&time1->date,
 678 		&time2->date);
 679 	if (day_comparison != 0)
 680 		return day_comparison;
 681 
 682 	if (time1->hour < time2->hour)
 683 		return -1;
 684 	if (time1->hour > time2->hour)
 685 		return 1;
 686 
 687 	if (time1->minute < time2->minute)
 688 		return -1;
 689 	if (time1->minute > time2->minute)
 690 		return 1;
 691 
 692 	/* The start times are exactly the same. */
 693 	return 0;
 694 }
 695 
 696 static gint
 697 compare_period_starts (gconstpointer arg1,
 698                        gconstpointer arg2)
 699 {
 700 	EMeetingFreeBusyPeriod *period1, *period2;
 701 
 702 	period1 = (EMeetingFreeBusyPeriod *) arg1;
 703 	period2 = (EMeetingFreeBusyPeriod *) arg2;
 704 
 705 	return compare_times (&period1->start, &period2->start);
 706 }
 707 
 708 static void
 709 ensure_periods_sorted (EMeetingAttendee *ia)
 710 {
 711 	EMeetingAttendeePrivate *priv;
 712 
 713 	priv = ia->priv;
 714 
 715 	if (priv->busy_periods_sorted)
 716 		return;
 717 
 718 	qsort (
 719 		priv->busy_periods->data, priv->busy_periods->len,
 720 		sizeof (EMeetingFreeBusyPeriod),
 721 		compare_period_starts);
 722 
 723 	priv->busy_periods_sorted = TRUE;
 724 }
 725 
 726 gboolean
 727 e_meeting_attendee_get_has_calendar_info (EMeetingAttendee *ia)
 728 {
 729 	EMeetingAttendeePrivate *priv;
 730 
 731 	priv = ia->priv;
 732 
 733 	return priv->has_calendar_info;
 734 }
 735 
 736 void
 737 e_meeting_attendee_set_has_calendar_info (EMeetingAttendee *ia,
 738                                           gboolean has_calendar_info)
 739 {
 740 	EMeetingAttendeePrivate *priv;
 741 
 742 	priv = ia->priv;
 743 
 744 	priv->has_calendar_info = has_calendar_info;
 745 }
 746 
 747 const GArray *
 748 e_meeting_attendee_get_busy_periods (EMeetingAttendee *ia)
 749 {
 750 	EMeetingAttendeePrivate *priv;
 751 
 752 	priv = ia->priv;
 753 
 754 	ensure_periods_sorted (ia);
 755 
 756 	return priv->busy_periods;
 757 }
 758 
 759 gint
 760 e_meeting_attendee_find_first_busy_period (EMeetingAttendee *ia,
 761                                            GDate *date)
 762 {
 763 	EMeetingAttendeePrivate *priv;
 764 	EMeetingFreeBusyPeriod *period;
 765 	gint lower, upper, middle = 0, cmp = 0;
 766 	GDate tmp_date;
 767 
 768 	priv = ia->priv;
 769 
 770 	/* Make sure the busy periods have been sorted. */
 771 	ensure_periods_sorted (ia);
 772 
 773 	/* Calculate the first day which could have a busy period which
 774 	 * continues onto our given date. */
 775 	tmp_date = *date;
 776 	g_date_subtract_days (&tmp_date, priv->longest_period_in_days);
 777 
 778 	/* We want the first busy period which starts on tmp_date. */
 779 	lower = 0;
 780 	upper = priv->busy_periods->len;
 781 
 782 	if (upper == 0)
 783 		return -1;
 784 
 785 	while (lower < upper) {
 786 		middle = (lower + upper) >> 1;
 787 
 788 		period = &g_array_index (priv->busy_periods,
 789 					 EMeetingFreeBusyPeriod, middle);
 790 
 791 		cmp = g_date_compare (&tmp_date, &period->start.date);
 792 
 793 		if (cmp == 0)
 794 			break;
 795 		else if (cmp < 0)
 796 			upper = middle;
 797 		else
 798 			lower = middle + 1;
 799 	}
 800 
 801 	/* There may be several busy periods on the same day so we step
 802 	 * backwards to the first one. */
 803 	if (cmp == 0) {
 804 		while (middle > 0) {
 805 			period = &g_array_index (priv->busy_periods,
 806 						 EMeetingFreeBusyPeriod, middle - 1);
 807 			if (g_date_compare (&tmp_date, &period->start.date) != 0)
 808 				break;
 809 			middle--;
 810 		}
 811 	} else if (cmp > 0) {
 812 		/* This means we couldn't find a period on the given day, and
 813 		 * the last one we looked at was before it, so if there are
 814 		 * any more periods after this one we return it. */
 815 		middle++;
 816 		if (priv->busy_periods->len <= middle)
 817 			return -1;
 818 	}
 819 
 820 	return middle;
 821 }
 822 
 823 gboolean
 824 e_meeting_attendee_add_busy_period (EMeetingAttendee *ia,
 825                                     gint start_year,
 826                                     gint start_month,
 827                                     gint start_day,
 828                                     gint start_hour,
 829                                     gint start_minute,
 830                                     gint end_year,
 831                                     gint end_month,
 832                                     gint end_day,
 833                                     gint end_hour,
 834                                     gint end_minute,
 835                                     EMeetingFreeBusyType busy_type,
 836                                     const gchar *summary,
 837                                     const gchar *location)
 838 {
 839 	EMeetingAttendeePrivate *priv;
 840 	EMeetingFreeBusyPeriod period;
 841 	gint period_in_days;
 842 
 843 	g_return_val_if_fail (ia != NULL, FALSE);
 844 	g_return_val_if_fail (E_IS_MEETING_ATTENDEE (ia), FALSE);
 845 	g_return_val_if_fail (busy_type < E_MEETING_FREE_BUSY_LAST, FALSE);
 846 	/* summary may be NULL (optional XFB data)  */
 847 	/* location may be NULL (optional XFB data) */
 848 
 849 	priv = ia->priv;
 850 
 851 	/* Check the dates are valid. */
 852 	if (!g_date_valid_dmy (start_day, start_month, start_year))
 853 		return FALSE;
 854 	if (!g_date_valid_dmy (end_day, end_month, end_year))
 855 		return FALSE;
 856 	if (start_hour < 0 || start_hour > 23)
 857 		return FALSE;
 858 	if (end_hour < 0 || end_hour > 23)
 859 		return FALSE;
 860 	if (start_minute < 0 || start_minute > 59)
 861 		return FALSE;
 862 	if (end_minute < 0 || end_minute > 59)
 863 		return FALSE;
 864 
 865 	g_date_clear (&period.start.date, 1);
 866 	g_date_clear (&period.end.date, 1);
 867 	g_date_set_dmy (&period.start.date, start_day, start_month, start_year);
 868 	g_date_set_dmy (&period.end.date, end_day, end_month, end_year);
 869 	period.start.hour = start_hour;
 870 	period.start.minute = start_minute;
 871 	period.end.hour = end_hour;
 872 	period.end.minute = end_minute;
 873 	period.busy_type = busy_type;
 874 
 875 	/* Check that the start time is before or equal to the end time. */
 876 	if (compare_times (&period.start, &period.end) > 0)
 877 		return FALSE;
 878 
 879 	/* If the busy_type is FREE, then there is no need to render it in UI */
 880 	if (busy_type == E_MEETING_FREE_BUSY_FREE)
 881 		goto done;
 882 
 883 	/* If the busy range is not set elsewhere, track it as best we can */
 884 	if (!priv->start_busy_range_set) {
 885 		if (!g_date_valid (&priv->busy_periods_start.date)) {
 886 			priv->busy_periods_start.date = period.start.date;
 887 			priv->busy_periods_start.hour = period.start.hour;
 888 			priv->busy_periods_start.minute = period.start.minute;
 889 		} else {
 890 			gint compare;
 891 
 892 			compare = g_date_compare (
 893 				&period.start.date,
 894 				&priv->busy_periods_start.date);
 895 
 896 			switch (compare) {
 897 			case -1:
 898 				priv->busy_periods_start.date = period.start.date;
 899 				priv->busy_periods_start.hour = period.start.hour;
 900 				priv->busy_periods_start.minute = period.start.minute;
 901 				break;
 902 			case 0:
 903 				if (period.start.hour < priv->busy_periods_start.hour
 904 				    || (period.start.hour == priv->busy_periods_start.hour
 905 					&& period.start.minute < priv->busy_periods_start.minute)) {
 906 					priv->busy_periods_start.date = period.start.date;
 907 					priv->busy_periods_start.hour = period.start.hour;
 908 					priv->busy_periods_start.minute = period.start.minute;
 909 					break;
 910 				}
 911 				break;
 912 			}
 913 		}
 914 	}
 915 
 916 	if (!priv->end_busy_range_set) {
 917 		if (!g_date_valid (&priv->busy_periods_end.date)) {
 918 			priv->busy_periods_end.date = period.end.date;
 919 			priv->busy_periods_end.hour = period.end.hour;
 920 			priv->busy_periods_end.minute = period.end.minute;
 921 		} else {
 922 			gint compare;
 923 
 924 			compare = g_date_compare (
 925 				&period.end.date,
 926 				&priv->busy_periods_end.date);
 927 
 928 			switch (compare) {
 929 			case 0:
 930 				if (period.end.hour > priv->busy_periods_end.hour
 931 				    || (period.end.hour == priv->busy_periods_end.hour
 932 					&& period.end.minute > priv->busy_periods_end.minute)) {
 933 					priv->busy_periods_end.date = period.end.date;
 934 					priv->busy_periods_end.hour = period.end.hour;
 935 					priv->busy_periods_end.minute = period.end.minute;
 936 					break;
 937 				}
 938 				break;
 939 			case 1:
 940 				priv->busy_periods_end.date = period.end.date;
 941 				priv->busy_periods_end.hour = period.end.hour;
 942 				priv->busy_periods_end.minute = period.end.minute;
 943 				break;
 944 			}
 945 		}
 946 	}
 947 
 948 	/* Setting of extended free/busy (XFB) data, if we have any. */
 949 	e_meeting_xfb_data_init (&(period.xfb));
 950 	e_meeting_xfb_data_set (&(period.xfb), summary, location);
 951 
 952 	g_array_append_val (priv->busy_periods, period);
 953 
 954 	period_in_days =
 955 		g_date_get_julian (&period.end.date) -
 956 		g_date_get_julian (&period.start.date) + 1;
 957 	priv->longest_period_in_days =
 958 		MAX (priv->longest_period_in_days, period_in_days);
 959 
 960 done:
 961 	priv->has_calendar_info = TRUE;
 962 	priv->busy_periods_sorted = FALSE;
 963 
 964 	return TRUE;
 965 }
 966 
 967 EMeetingTime
 968 e_meeting_attendee_get_start_busy_range (EMeetingAttendee *ia)
 969 {
 970 	EMeetingAttendeePrivate *priv;
 971 
 972 	priv = ia->priv;
 973 
 974 	return priv->busy_periods_start;
 975 }
 976 
 977 EMeetingTime
 978 e_meeting_attendee_get_end_busy_range (EMeetingAttendee *ia)
 979 {
 980 	EMeetingAttendeePrivate *priv;
 981 
 982 	priv = ia->priv;
 983 
 984 	return priv->busy_periods_end;
 985 }
 986 
 987 gboolean
 988 e_meeting_attendee_set_start_busy_range (EMeetingAttendee *ia,
 989                                          gint start_year,
 990                                          gint start_month,
 991                                          gint start_day,
 992                                          gint start_hour,
 993                                          gint start_minute)
 994 {
 995 	EMeetingAttendeePrivate *priv;
 996 
 997 	g_return_val_if_fail (E_IS_MEETING_ATTENDEE (ia), FALSE);
 998 
 999 	priv = ia->priv;
1000 
1001 	/* Check the dates are valid. */
1002 	if (!g_date_valid_dmy (start_day, start_month, start_year))
1003 		return FALSE;
1004 	if (start_hour < 0 || start_hour > 23)
1005 		return FALSE;
1006 	if (start_minute < 0 || start_minute > 59)
1007 		return FALSE;
1008 
1009 	g_date_clear (&priv->busy_periods_start.date, 1);
1010 	g_date_set_dmy (
1011 		&priv->busy_periods_start.date,
1012 		start_day, start_month, start_year);
1013 	priv->busy_periods_start.hour = start_hour;
1014 	priv->busy_periods_start.minute = start_minute;
1015 
1016 	priv->start_busy_range_set = TRUE;
1017 
1018 	return TRUE;
1019 }
1020 
1021 gboolean
1022 e_meeting_attendee_set_end_busy_range (EMeetingAttendee *ia,
1023                                        gint end_year,
1024                                        gint end_month,
1025                                        gint end_day,
1026                                        gint end_hour,
1027                                        gint end_minute)
1028 {
1029 	EMeetingAttendeePrivate *priv;
1030 
1031 	g_return_val_if_fail (E_IS_MEETING_ATTENDEE (ia), FALSE);
1032 
1033 	priv = ia->priv;
1034 
1035 	/* Check the dates are valid. */
1036 	if (!g_date_valid_dmy (end_day, end_month, end_year))
1037 		return FALSE;
1038 	if (end_hour < 0 || end_hour > 23)
1039 		return FALSE;
1040 	if (end_minute < 0 || end_minute > 59)
1041 		return FALSE;
1042 
1043 	g_date_clear (&priv->busy_periods_end.date, 1);
1044 	g_date_set_dmy (
1045 		&priv->busy_periods_end.date,
1046 		end_day, end_month, end_year);
1047 	priv->busy_periods_end.hour = end_hour;
1048 	priv->busy_periods_end.minute = end_minute;
1049 
1050 	priv->end_busy_range_set = TRUE;
1051 
1052 	return TRUE;
1053 }
1054 
1055 /* Clears all busy times for the given attendee. */
1056 void
1057 e_meeting_attendee_clear_busy_periods (EMeetingAttendee *ia)
1058 {
1059 	EMeetingAttendeePrivate *priv;
1060 
1061 	g_return_if_fail (E_IS_MEETING_ATTENDEE (ia));
1062 
1063 	priv = ia->priv;
1064 
1065 	g_array_set_size (priv->busy_periods, 0);
1066 	priv->busy_periods_sorted = TRUE;
1067 
1068 	g_date_clear (&priv->busy_periods_start.date, 1);
1069 	priv->busy_periods_start.hour = 0;
1070 	priv->busy_periods_start.minute = 0;
1071 
1072 	g_date_clear (&priv->busy_periods_end.date, 1);
1073 	priv->busy_periods_end.hour = 0;
1074 	priv->busy_periods_end.minute = 0;
1075 
1076 	priv->longest_period_in_days = 0;
1077 }