Example #1
0
/***********************************************************************
 *
 * FUNCTION:    DateCompare
 *
 * DESCRIPTION: This routine compares two dates.
 *
 * PARAMETERS:  d1 - a date 
 *              d2 - a date 
 *
 * RETURNED:    if d1 > d2  returns a positive int
 *              if d1 < d2  returns a negative int
 *              if d1 = d2  returns zero
 *
 * NOTE: This routine treats the DateType structure like an unsigned int,
 *       it depends on the fact the the members of the structure are ordered
 *       year, month, day form high bit to low low bit.
 *
 ***********************************************************************/
Int16 DateCompare(DateType d1, DateType d2)
{
    UInt16 int1, int2;
    
    int1 = DateToInt(d1);
    int2 = DateToInt(d2);
    
    if (int1 > int2) return (1);
    else if (int1 < int2) return (-1);
    return 0;
}
Example #2
0
/***********************************************************************
 *
 * FUNCTION:    RepeatSelectEndDate
 *
 * DESCRIPTION: This routine selects the end date of a repeating event.
 *
 * PARAMETERS:  event - pointer to a popup select event
 *
 * RETURNED:    nothing
 *
 ***********************************************************************/
static void RepeatSelectEndDate(EventType* event) {
  Int16 month, day, year;
  Char* titleP = NULL;
  MemHandle titleH = NULL;

  /* "No due date" items selected? */
  if (event->data.popSelect.selection == repeatNoEndDateItem)
    DateToInt(d.repeat_end_date) = apptNoEndDate;

  /* "Select date" item selected? */
  else if (event->data.popSelect.selection == repeatChooseDateItem) {
    if (DateToInt (d.repeat_end_date) == apptNoEndDate) {
      year = d.frm_date.year;
      month = d.frm_date.month;
      day = d.frm_date.day;
    } else {
      year = d.repeat_end_date.year + firstYear;
      month = d.repeat_end_date.month;
      day = d.repeat_end_date.day;
    }
    
    titleH = DmGetResource(strRsc, endDateTitleString);
    titleP = MemHandleLock(titleH);
    
    if (SelectDay (selectDayByDay, &month, &day, &year, titleP)) {
      d.repeat_end_date.day = day;
      d.repeat_end_date.month = month;
      d.repeat_end_date.year = year - firstYear;
      
      /* Make sure the end date is not before the start date. */
      if (DateToInt(d.repeat_end_date) < DateToInt (d.frm_date)) {
	SndPlaySystemSound (sndError);
	DateToInt (d.repeat_end_date) = apptNoEndDate;
      }
    }
    
    MemHandleUnlock(titleH);
  }

  RepeatSetDateTrigger(d.repeat_end_date);
}
Example #3
0
/***********************************************************************
 *
 * FUNCTION:    RepeatSetDateTrigger
 *
 * DESCRIPTION: This routine sets the label of the trigger that displays
 *              the end date of a repeating appointment.
 *
 * PARAMETERS:  endDate	- date or -1 if no end date
 *
 * RETURNED:    nothing
 *
 * NOTES:
 *      This routine assumes that the memory allocated for the label of
 *      the due date trigger is large enough to hold the lagest posible
 *      label. This label's memory is reserved by initializing the label
 *      in the resource file.
 *
 ***********************************************************************/
static void RepeatSetDateTrigger (DateType endDate) {
  FormType* frm = FrmGetFormPtr(RepeatForm);
  ListType* lst = GetObjectPointer(frm, RepeatEndOnList);
  ControlType* ctl = GetObjectPointer(frm, RepeatEndOnTrigger);
  Char* label = (Char*)CtlGetLabel(ctl); /* OK to cast; we call CtlSetLabel */

  ASSERT(lst);
  ASSERT(ctl);
  ASSERT(label);

  if (DateToInt(endDate) == apptNoEndDate) {
    StrCopy(label, LstGetSelectionText(lst, repeatNoEndDateItem));
    LstSetSelection(lst, noEndDateItem);
  } else {
    /* Format the end date into a string. */
    DateToDOWDMFormat(endDate.month, endDate.day, endDate.year + firstYear,
		      PrefGetPreference(prefDateFormat), label);
    
    LstSetSelection(lst, repeatChooseDateItem);
  }
  
  CtlSetLabel(ctl, label);
}
Example #4
0
/***********************************************************************
 *
 * FUNCTION:    RepeatChangeType
 *
 * DESCRIPTION: This routine changes the ui gadgets in the repeat dialog
 *              such that they match the newly selected repeat type.  The
 *              routine is called when one of the repeat type push buttons
 *              are pushed.
 *
 * PARAMETERS:  event - pointer to and event
 *
 * RETURNED:    nothing
 *
 ***********************************************************************/
static void RepeatChangeType(EventType* event) {
  UInt16 id;
  FormType* frm = FrmGetFormPtr(RepeatForm);
  const RepeatType oldType = d.repeat_event_type;
  RepeatType newType;
  RepeatInfoType repeat;

  /* If the type if monthly default to monthly-by-date. */
  newType = (RepeatType) (event->data.ctlSelect.controlID - RepeatNone);
  if (newType > repeatWeekly) 
    newType++;

  if (oldType == newType)
    return;

  /* Initialize the UI gadgets. */
  if (newType == d.tmp_repeat.repeatType) {
    RepeatSetUIValues(frm, &d.tmp_repeat);

    /*
    ** If reselecting current repeat type, reset d.repeat_end_date global
    ** to current date so if user attemps to "choose" a new day, the
    ** default matches date displayed as opposed to last date picked
    ** last in choose form.
    */
    d.repeat_end_date = d.tmp_repeat.repeatEndDate;
  } else {
    repeat.repeatType = newType;

    /*
    ** When switching to a repeat type different from the current
    ** setting, always start user with default end date and frequency
    ** settings.
    */
    DateToInt(repeat.repeatEndDate) = defaultRepeatEndDate;
    DateToInt(d.repeat_end_date) = defaultRepeatEndDate;
    repeat.repeatFrequency = defaultRepeatFrequency;
    
    repeat.repeatStartOfWeek = PrefGetPreference(prefWeekStartDay);

    if (newType == repeatWeekly) {
      repeat.repeatOn = (1 << DayOfWeek(d.frm_date.month,
					d.frm_date.day,
					d.frm_date.year/*+firstYear*/));
    } else if (newType == repeatMonthlyByDay) {
      repeat.repeatOn = DayOfMonth(d.frm_date.month,
				   d.frm_date.day,
				   d.frm_date.year/* + firstYear*/);
    } else {
      repeat.repeatOn = 0;
    }

    RepeatSetUIValues (frm, &repeat);
  }
  
  /*
  ** Hide the UI gadgets that are unique to the repeat type we are
  ** no longer editing.
  */
  switch (oldType) {
  case repeatNone:
    HideObject(frm, RepeatNoRepeatLabel);
    break;

  case repeatHourly:
    HideObject(frm, RepeatHoursLabel);
    break;

  case repeatDaily:
    HideObject(frm, RepeatDaysLabel);
    break;

  case repeatWeekly:
    HideObject(frm, RepeatWeeksLabel);
    for (id = RepeatRepeatOnLabel; id <= RepeatDayOfWeek7PushButton; id++)
      HideObject (frm, id);
    break;

  case repeatMonthlyByDay:
  case repeatMonthlyByDate:
    HideObject(frm, RepeatMonthsLabel);
    for (id = RepeatByLabel; id <= RepeatByDatePushButton; id++)
      HideObject (frm, id);
    break;

  case repeatYearly:
    HideObject(frm, RepeatYearsLabel);
    break;
  }

  /* Handle switching to or from "no" repeat. */
  if (oldType == repeatNone) {
    ShowObject(frm, RepeatEveryLabel);
    ShowObject(frm, RepeatFrequenceField);
    ShowObject(frm, RepeatEndOnLabel);
    ShowObject(frm, RepeatEndOnTrigger);
  } else if (newType == repeatNone) {
    HideObject(frm, RepeatEveryLabel);
    HideObject(frm, RepeatFrequenceField);
    HideObject(frm, RepeatEndOnLabel);
    HideObject(frm, RepeatEndOnTrigger);
  }

  /* Show the UI object that are appropriate for the new repeat type. */
  switch (newType) {
  case repeatNone:
    ShowObject(frm, RepeatNoRepeatLabel);
    break;

  case repeatHourly:
    ShowObject(frm, RepeatHoursLabel);
    break;

  case repeatDaily:
    ShowObject(frm, RepeatDaysLabel);
    break;

  case repeatWeekly:
    ShowObject(frm, RepeatWeeksLabel);
    ShowObject(frm, RepeatRepeatOnLabel);
    for (id = RepeatRepeatOnLabel; id <= RepeatDayOfWeek7PushButton; id++)
      ShowObject(frm, id);
    break;

  case repeatMonthlyByDay:
  case repeatMonthlyByDate:
    ShowObject(frm, RepeatMonthsLabel);
    ShowObject(frm, RepeatByLabel);
    ShowObject(frm, RepeatByDayPushButton);
    ShowObject(frm, RepeatByDatePushButton);
    break;

  case repeatYearly:
    ShowObject(frm, RepeatYearsLabel);
    break;
  }

  d.repeat_event_type = newType;

  /* Update the display of the repeat descrition. */
  RepeatDrawDescription(frm);
}
Example #5
0
/***********************************************************************
 *
 * FUNCTION:    NextRepeat
 *
 * DESCRIPTION: This routine computes the date of the next
 *              occurrence of a repeating appointment.
 *
 * PARAMETERS:  rec     - a pointer to a DiddleBug record
 *              date    - passed:   date to start from
 *                        returned: date of next occurrence
 *
 * RETURNED:    true if the appointment occurs again
 *
 ***********************************************************************/
Boolean NextRepeat(DiddleBugRecordType* rec, DateTimeType* dateP) {

  /*
  ** Get the frequency on occurrence
  **(ex: every 2nd day, every 3rd month, etc).
  */ 
  const UInt16 freq = rec->repeatInfo.repeatFrequency;
  
  Int16  i = 0;
  UInt16 day;
  UInt16 year;
  UInt16 adjust;
  UInt16 weeksDiff;
  UInt16 monthsDiff;
  UInt16 daysInMonth;
  UInt16 dayOfWeek;
  UInt16 apptWeekDay;
  UInt16 firstDayOfWeek;
  UInt16 daysTilNext;
  UInt16 monthsTilNext;
  UInt32 dateInDays;
  UInt32 startInDays;
  DateType start, date, when, next;
  DateTimeType nextReal;
  UInt32 startSecs, nextSecs;

  DateSecondsToDate(TimDateTimeToSeconds(dateP), &date);
  TimSecondsToDateTime(rec->alarmSecs, &nextReal);
  nextReal.year = dateP->year;
  nextReal.month = dateP->month;
  nextReal.day = dateP->day;
  nextReal.weekDay = dateP->weekDay;

  /* Calculate alarm date */
  DateSecondsToDate(rec->alarmSecs, &when);

  /* Is the date passed after the end date of the appointment? */
  if (DateCompare(date, rec->repeatInfo.repeatEndDate) > 0)
    return false;

  /* Is the date passed before the start date of the appointment? */
  if (DateCompare(date, when) < 0)
    date = when;
  
  /* Get the date of the first occurrecne of the appointment. */
  start = when;

  switch (rec->repeatInfo.repeatType) {
    /* Hourly repeating appointment */
  case repeatHourly:
    startSecs = TimDateTimeToSeconds(dateP);
    nextSecs = rec->alarmSecs;
    while (nextSecs < startSecs)
      nextSecs += freq * hoursInSeconds;
    
    TimSecondsToDateTime(nextSecs, &nextReal);
    DateSecondsToDate(nextSecs, &next);
    break;

    /* Daily repeating appointment. */
  case repeatDaily:
    dateInDays = DateToDays(date);
    startInDays = DateToDays(start);
    daysTilNext = (dateInDays - startInDays + freq - 1) / freq * freq;
    if (startInDays + daysTilNext > (UInt32) maxDays)
      return false;
    DateDaysToDate (startInDays + daysTilNext, &next);
    break;
    
    /*
    ** Weekly repeating appointment (ex: every Monday and Friday).
    ** Yes, weekly repeating appointment can occur more then once a
    ** week.
    */
  case repeatWeekly:
    dateInDays = DateToDays(date);
    startInDays = DateToDays(start);
    
    firstDayOfWeek = (DayOfWeek (1, 1, firstYear) -
		      rec->repeatInfo.repeatStartOfWeek + daysInWeek) % daysInWeek;

    dayOfWeek = DayOfWeek(date.month, date.day, date.year+firstYear);
    apptWeekDay = (dayOfWeek - rec->repeatInfo.repeatStartOfWeek +
		   daysInWeek) % daysInWeek;

    /*
    ** Are we in a week in which the appointment occurrs, if not
    ** move to that start of the next week in which the appointment
    ** does occur.
    */
    weeksDiff = (((dateInDays + firstDayOfWeek) / daysInWeek) -
		 ((startInDays + firstDayOfWeek) / daysInWeek)) % freq;
    if (weeksDiff) {
      adjust = ((freq - weeksDiff) * daysInWeek) - apptWeekDay;
      apptWeekDay = 0;
      dayOfWeek = (dayOfWeek + adjust) % daysInWeek;
    } else {
      adjust = 0;
    }

    /* Find the next day on which the appointment repeats. */
    for (; i < daysInWeek; i++) {
      if (rec->repeatInfo.repeatOn & (1 << dayOfWeek))
	break;
      
      adjust++;
      
      if (++dayOfWeek == daysInWeek)
	dayOfWeek = 0;

      if (++apptWeekDay == daysInWeek)
	adjust += (freq - 1) * daysInWeek;
    }

    if (dateInDays + adjust > (UInt32) maxDays)
      return false;
    
    DateDaysToDate (dateInDays + adjust, &next);
    break;

    /*
    ** Monthly-by-day repeating appointment
    ** (ex: the 3rd Friday of every month).
    */
  case repeatMonthlyByDay:
    /* Compute the number of month until the appointment repeats again. */
    monthsTilNext = ((((date.year - start.year) * monthsInYear) +
		      (date.month - start.month)) + freq - 1) / freq * freq;

    while (true) {
      year = start.year + (start.month - 1 + monthsTilNext) / monthsInYear;
      if (year >= numberOfYears)
	return false;
      
      next.year = year;
      next.month = (start.month - 1 + monthsTilNext) % monthsInYear + 1;
      
      dayOfWeek = DayOfWeek (next.month, 1, next.year+firstYear);
      if ((rec->repeatInfo.repeatOn % daysInWeek) >= dayOfWeek)
	day = rec->repeatInfo.repeatOn - dayOfWeek + 1;
      else
	day = rec->repeatInfo.repeatOn + daysInWeek - dayOfWeek + 1;
      
      /*
      ** If repeat-on day is between the last sunday and the last
      ** saturday, make sure we're not passed the end of the month.
      */
      if ( (rec->repeatInfo.repeatOn >= domLastSun) &&
	   (day > DaysInMonth (next.month, next.year+firstYear))) {
	day -= daysInWeek;
      }
      next.day = day;

      /*
      ** Its posible that "next date" calculated above is
      ** before the date passed.  If so, move forward
      ** by the length of the repeat freguency and preform
      ** the calculation again.
      */
      if (DateToInt(date) > DateToInt(next))
	monthsTilNext += freq;
      else
	break;
    }
    break;

    /*
    ** Monthly-by-date repeating appointment
    ** (ex: the 15th of every month).
    */
  case repeatMonthlyByDate:
    /* Compute the number of month until the appointment repeats again. */
    monthsDiff = (date.year - start.year) * monthsInYear + date.month - start.month;
    monthsTilNext = (monthsDiff + freq - 1) / freq * freq;

    if (date.day > start.day && !(monthsDiff % freq))
      monthsTilNext += freq;

    year = start.year +	(start.month - 1 + monthsTilNext) / monthsInYear;
    if (year >= numberOfYears)
      return false;

    next.year = year;
    next.month = (start.month - 1 + monthsTilNext) % monthsInYear + 1;
    next.day = start.day;

    /* Make sure we're not passed the last day of the month. */
    daysInMonth = DaysInMonth(next.month, next.year+firstYear);
    if (next.day > daysInMonth)
      next.day = daysInMonth;
    break;

    /* Yearly repeating appointment. */
  case repeatYearly:
    next.day = start.day;
    next.month = start.month;
    
    year = start.year + ((date.year - start.year + freq - 1) / freq * freq);

    if (date.month > start.month || 
	(date.month == start.month && date.day > start.day))
      year += freq;

    /* Specal leap day processing. */
    if (next.month == february && next.day == 29 &&
	next.day > DaysInMonth(next.month, year+firstYear)) {
      next.day = DaysInMonth (next.month, year+firstYear);
    }
    if (year >= numberOfYears)
      return false;
    
    next.year = year;
    break;

  default:
    /* ignore */
  }

  /* Is the next occurrence after the end date of the appointment? */
  if (DateCompare(next, rec->repeatInfo.repeatEndDate) > 0)
    return false;

  dateP->day = next.day;
  dateP->month = next.month;
  dateP->year = next.year + firstYear;
  dateP->hour = nextReal.hour;
  dateP->minute = nextReal.minute;
  dateP->second = nextReal.second;

  return true;
}
Example #6
0
/*
** Compare two dates
*/
extern inline Int16 DateCompare(DateType d1, DateType d2) {
  return (DateToInt(d1) > DateToInt(d2)) ? 1 : ((DateToInt(d1) < DateToInt(d2)) ? -1 : 0);
}
Example #7
0
Boolean NextRepeat (ApptDBRecordPtr apptRec, DatePtr dateP) 
{
	Int16  i;
	UInt16 day;
	UInt16 freq;
	UInt16 year;
	UInt16 adjust;
	UInt16 weeksDiff;
	UInt16 monthsDiff;
	UInt16 daysInMonth;
	UInt16 dayOfWeek;
	UInt16 apptWeekDay;
	UInt16 firstDayOfWeek;
	UInt16 daysTilNext;
	UInt16 monthsTilNext;
	UInt32 dateInDays;
	UInt32 startInDays;
	DateType start;
	DateType date;
	DateType next;

	date = *dateP;

	// Is the date passed after the end date of the appointment?
	if (DateCompare (date, apptRec->repeat->repeatEndDate) > 0)
		return (false);
	
	// Is the date passed before the start date of the appointment?
	if (DateCompare (date, apptRec->when->date) < 0)
		date = apptRec->when->date;

	// Get the frequency on occurrecne (ex: every 2nd day, every 3rd month, etc).  
	freq = apptRec->repeat->repeatFrequency;
	
	// Get the date of the first occurrecne of the appointment.
	start = apptRec->when->date;
	

	switch (apptRec->repeat->repeatType)
    {
		// Daily repeating appointment.
    case repeatDaily:
        dateInDays = DateToDays (date);
        startInDays = DateToDays (start);
        daysTilNext = (dateInDays - startInDays + freq - 1) / freq * freq;
        if (startInDays + daysTilNext > (UInt32) maxDays)
            return (false);
        DateDaysToDate (startInDays + daysTilNext, &next);
        break;
			


		// Weekly repeating appointment (ex: every Monday and Friday). 
		// Yes, weekly repeating appointment can occur more then once a
		// week.
    case repeatWeekly:
        dateInDays = DateToDays (date);
        startInDays = DateToDays (start);

        firstDayOfWeek = (DayOfWeek (1, 1, firstYear) - 
                          apptRec->repeat->repeatStartOfWeek + daysInWeek) % daysInWeek;

        dayOfWeek = DayOfWeek (date.month, date.day, date.year+firstYear);
        apptWeekDay = (dayOfWeek - apptRec->repeat->repeatStartOfWeek +
                       daysInWeek) % daysInWeek;

        // Are we in a week in which the appointment occurrs, if not 
        // move to that start of the next week in which the appointment
        // does occur.
        weeksDiff = (((dateInDays + firstDayOfWeek) / daysInWeek) - 
                     ((startInDays + firstDayOfWeek) / daysInWeek)) %freq;
        if (weeksDiff)
        {
            adjust = ((freq - weeksDiff) * daysInWeek)- apptWeekDay;
            apptWeekDay = 0;
            dayOfWeek = (dayOfWeek + adjust) % daysInWeek;
        }
        else
            adjust = 0;
			
        // Find the next day on which the appointment repeats.
        for (i = 0; i < daysInWeek; i++)
        {
            if (apptRec->repeat->repeatOn & (1 << dayOfWeek)) break;
            adjust++;
            if (++dayOfWeek == daysInWeek)
                dayOfWeek = 0;
            if (++apptWeekDay == daysInWeek)
                adjust += (freq - 1) * daysInWeek;
        }

        if (dateInDays + adjust > (UInt32) maxDays)
            return (false);
        DateDaysToDate (dateInDays + adjust, &next);
//			next = date;
//			DateAdjust (&next, adjust);
        break;



		// Monthly-by-day repeating appointment (ex: the 3rd Friday of every
		// month).
    case repeatMonthlyByDay:
        // Compute the number of month until the appointment repeats again.
        monthsTilNext = (date.month - start.month);

        monthsTilNext = ((((date.year - start.year) * monthsInYear) + 
                          (date.month - start.month)) + freq - 1) /
            freq * freq;

        while (true)
        {
            year = start.year + 
                (start.month - 1 + monthsTilNext) / monthsInYear;
            if (year >= numberOfYears)
                return (false);

            next.year = year;
            next.month = (start.month - 1 + monthsTilNext) % monthsInYear + 1;
	
            dayOfWeek = DayOfWeek (next.month, 1, next.year+firstYear);
            if ((apptRec->repeat->repeatOn % daysInWeek) >= dayOfWeek)
                day = apptRec->repeat->repeatOn - dayOfWeek + 1;
            else
                day = apptRec->repeat->repeatOn + daysInWeek - dayOfWeek + 1;
	
            // If repeat-on day is between the last sunday and the last
            // saturday, make sure we're not passed the end of the month.
            if ( (apptRec->repeat->repeatOn >= domLastSun) &&
                 (day > DaysInMonth (next.month, next.year+firstYear)))
            {
                day -= daysInWeek;
            }
            next.day = day;

            // Its posible that "next date" calculated above is 
            // before the date passed.  If so, move forward
            // by the length of the repeat freguency and preform
            // the calculation again.
            if ( DateToInt(date) > DateToInt (next))
                monthsTilNext += freq;
            else
                break;
        }
        break;						



		// Monthly-by-date repeating appointment (ex: the 15th of every
		// month).
    case repeatMonthlyByDate:
        // Compute the number of month until the appointment repeats again.
        monthsDiff = ((date.year - start.year) * monthsInYear) + 
            (date.month - start.month);
        monthsTilNext = (monthsDiff + freq - 1) / freq * freq;

        if ((date.day > start.day) && (!(monthsDiff % freq)))
            monthsTilNext += freq;
				
        year = start.year + 
            (start.month - 1 + monthsTilNext) / monthsInYear;
        if (year >= numberOfYears)
            return (false);

        next.year = year;
        next.month = (start.month - 1 + monthsTilNext) % monthsInYear + 1;
        next.day = start.day;

        // Make sure we're not passed the last day of the month.
        daysInMonth = DaysInMonth (next.month, next.year+firstYear);
        if (next.day > daysInMonth)
            next.day = daysInMonth;
        break;



		// Yearly repeating appointment.
    case repeatYearly:
        next.day = start.day;
        next.month = start.month;

        year = start.year + 
            ((date.year - start.year + freq - 1) / freq * freq);
			
        if ((date.month > start.month) ||
            ((date.month == start.month) && (date.day > start.day)))
            year += freq;

        // Specal leap day processing.
        if ( (next.month == february) && (next.day == 29) &&
             (next.day > DaysInMonth (next.month, year+firstYear)))
        {
            next.day = DaysInMonth (next.month, year+firstYear);
        }				      
        if (year >= numberOfYears)
            return (false);

        next.year = year;	
        break;
    default:
        break;
    }

	// Is the next occurrence after the end date of the appointment?
	if (DateCompare (next, apptRec->repeat->repeatEndDate) > 0)
		return (false);

	ErrFatalDisplayIf ((DateToInt (next) < DateToInt (*dateP)),
                       "Calculation error");

	*dateP = next;
	return (true);
}
Example #8
0
/** 
 * @brief
 * @param dbP Happydays DB pointer
 * @param AddrCategory The category of Address to be displayed
 * @param start Start position
 * @return The number of total Item
 * @remarks
 * @endif
 */
UInt16 AddrGetHappyDays(DmOpenRef dbP, UInt16 AddrCategory, DateType start)
{
    UInt16 totalItems;
    UInt16 recordNum = 0;
    MemHandle recordH = 0;
    LineItemPtr ptr;
    PackedHappyDays* rp;
    HappyDays r;
    DateType converted;          
    UInt16 currindex = 0;
	Int16 age;

    // if exist, free the memory
    //
    if (gTableRowHandle) {
        MemHandleFree(gTableRowHandle);
        gTableRowHandle = 0;
    }
    
    totalItems = DmNumRecordsInCategory(dbP, AddrCategory);
    if (totalItems > 0) {
        gTableRowHandle = MemHandleNew(sizeof(LineItemType)* totalItems);
        ErrFatalDisplayIf(!gTableRowHandle, "Out of memory");
        
        if ((ptr = MemHandleLock(gTableRowHandle))) {
            for (recordNum = 0; recordNum < totalItems; recordNum++) {
                if ((recordH = DmQueryNextInCategory(dbP, &currindex,
                                                     (UInt16)AddrCategory))) {
                
                    ptr[recordNum].birthRecordNum = currindex;

                    rp = (PackedHappyDays *) MemHandleLock(recordH);
                    /*
                     * Build the unpacked structure for an AddressDB
                     * record.  It is just a bunch of pointers into the rp
                     * structure.
                     */
                    UnpackHappyDays(&r, rp);

                    // original r(in MainDB) not changed
                    //     local change for LineItemType
                    //
					converted = r.date;

                    if (r.flag.bits.nthdays) {
                        int syear, smonth, sday;

                        if (r.flag.bits.lunar || r.flag.bits.lunar_leap) {
                            if  (lunarL2S(lunarRefNum, converted.year + firstYear,
                                          converted.month, converted.day,
                                          r.flag.bits.lunar_leap, &syear, &smonth, &sday) != errNone) {
                                MemHandleUnlock(recordH);
                                currindex++;
                                recordNum--;
                                totalItems--;

                                continue;
                            }
                            converted.day = sday;
                            converted.month = smonth;
                            converted.year = syear - firstYear;
                        }
                        DateAdjust(&converted, r.nth);

                        if (DateToDays(converted) < DateToDays(start)) {
                        	MemHandleUnlock(recordH);
                        	currindex++;
                            recordNum--;
                            totalItems--;

                            continue;
                        }
                        
                    }
                    else if (r.flag.bits.lunar || r.flag.bits.lunar_leap) {

                        if (!FindNearLunar(&converted, start,
                                           r.flag.bits.lunar_leap)) {
                            // ignore the records
                            //
                            converted.year = INVALID_CONV_DATE;
                            // max year(for sorting)
                            //   indicate for invalid date
                            
                        }
                    }
                    else if (r.flag.bits.solar) {
                        int maxtry = 4;
						DateType dt;

						dt = start;

                        DateToInt(dt) = 
							(DateToInt(dt) > DateToInt(converted))
                            ? DateToInt(dt) : DateToInt(converted);

                        if (converted.month < dt.month ||
                            ( converted.month == dt.month
                              && converted.day < dt.day)) {
                            // birthdate is in last year?
                            while (DaysInMonth(converted.month, ++dt.year) < converted.day
                                   && maxtry-- > 0) 
                                ;
                        }
                        else {
                            while (DaysInMonth(converted.month, dt.year) < converted.day
                                   && maxtry-- >0) {
                                dt.year++;
                            }
                            
                        }

                        if (maxtry >0) converted.year = dt.year;
                        else {
                            converted.year = INVALID_CONV_DATE;
                            // max year
                            //   indicate for invalid date
                        }
                    }
        
					if (converted.year != INVALID_CONV_DATE
                        && !r.flag.bits.nthdays 
						&& r.flag.bits.year 
						&& (age = CalculateAge(converted, r.date, r.flag)) >= 0) {
						// calculate age if year exists
						//
						ptr[recordNum].age = age;
					}
					else {
						ptr[recordNum].age = -1;
					}

                    // save the converted data
                    //
                    ptr[recordNum].date = converted;

                    MemHandleUnlock(recordH);
                    currindex++;
                }
            }
            
            // sort the order if sort order is converted date
            //
            if (gPrefsR.sort == 1) {      	// date sort
                SysInsertionSort(ptr, totalItems, sizeof(LineItemType),
                                 (_comparF *)CompareHappyDaysFunc, 1L);
            }
			else if (gPrefsR.sort == 3) {  	// age sort
                SysInsertionSort(ptr, totalItems, sizeof(LineItemType),
                                 (_comparF *)CompareAgeFunc, 1L);
            }
			else if (gPrefsR.sort == 2) {	    // age sort(re)
                SysInsertionSort(ptr, totalItems, sizeof(LineItemType),
                                 (_comparF *)CompareAgeFunc, -1L);
            }
            
            MemPtrUnlock(ptr);
        } else return 0;
    }
    
    return totalItems;
}
Example #9
0
/**
 * @brief Read the happydays information from address db, and insert into Happydays DB
 * @param frm StartForm to display indicator bars
 * @return If success, return true, or return false
 */
Boolean NewUpdateHappyDaysDB(FormPtr frm)
{
    UInt16 currIndex = 0;
    PrvAddrPackedDBRecord *rp;
    AddrDBRecordType r;
    MemHandle recordH = 0;
    UInt16 recordNum;
    int i = 0, indicateNext;
    int step;

    // create the happydays cache db
    HappyDays   hd;
    Boolean     ignore = false;         // ignore error record
    Char*       hdField;
    UInt16      addrattr, index;
    Char        *p, *q, *end;
    Int16       err;

    // display collecting information
    //
    FrmDrawForm(frm);

    // clean up old database
    //
    CleanupHappyDaysCache(MainDB);

    recordNum = DmNumRecords(AddressDB);
    indicateNext = step = recordNum / INDICATE_NUM;

    if (recordNum > 50) initIndicate();

    while (1) {
        char *name1, *name2;
        Int8 whichField;        // birthday field or note field?

        recordH = DmQueryNextInCategory(AddressDB, &currIndex,
                                        dmAllCategories);
        if (!recordH) break;
        if (i++ == indicateNext) {
            if (recordNum > 50) displayNextIndicate( (i-1) / step);
            indicateNext += step;
        }

        DmRecordInfo(AddressDB, currIndex, &addrattr, NULL, NULL);
        addrattr &= dmRecAttrCategoryMask;      // get category info

        rp = (PrvAddrPackedDBRecord*)MemHandleLock(recordH);
        /*
         * Build the unpacked structure for an AddressDB record.  It
         * is just a bunch of pointers into the rp structure.
         */
        NewAddrUnpack(rp, &r);

        if ( (gHappyDaysField <= 0 || !r.fields[gHappyDaysField])
                // there is no birthday info(trick. should check flags, but I think it is ok)
                //
                && DateToInt(r.birthdayInfo.birthdayDate) == 0
                && !(gPrefsR.scannote && r.fields[note]
                     && StrStr(r.fields[note], gPrefsR.notifywith) ) ) {

            // If there is not exist Happydays field or note field, or internal birthday field(in NEW PIMS)
            //
            MemHandleUnlock(recordH);
            currIndex++;
            continue;
        }

        MemSet(&hd, sizeof(hd), 0);
        hd.addrRecordNum = currIndex;
        if (DetermineRecordName(&r, gSortByCompany, &hd.name1, &hd.name2)) {
            // name 1 has priority;
            hd.flag.bits.priority_name1 = 1;
        }

        // ===========================================================
        // Process Birthday field first
        // ===========================================================
        if (DateToInt(r.birthdayInfo.birthdayDate) != 0) {
            hd.date = r.birthdayInfo.birthdayDate;
            hd.flag.bits.year = 1;
            hd.flag.bits.solar = 1;

            // maintain address book order(name order)
            //      list order is determined by sort
            err = HDNewRecord(MainDB, &hd, &index);
            if (!err) {
                UInt16 attr;
                // set the category of the new record to the category
                // it belongs in
                DmRecordInfo(MainDB, index, &attr, NULL, NULL);
                attr &= ~dmRecAttrCategoryMask;
                attr |= addrattr;

                DmSetRecordInfo(MainDB, index, &attr, NULL);
                DmReleaseRecord(MainDB, index, true);
            }
        }
        // ===========================================================

        // save the temporary name
        name1 = hd.name1;
        name2 = hd.name2;

        if (gHappyDaysField >= 0 && r.fields[gHappyDaysField]) {
            whichField = gHappyDaysField;
        }
        else if (gPrefsR.scannote     // scanNote & exists
                 && r.fields[note]
                 && StrStr(r.fields[note], gPrefsR.notifywith)) {
            whichField = note;
        }
        else whichField = -1;

        while (whichField >= 0) {

            if (whichField == note) {
                p = StrStr(r.fields[note], gPrefsR.notifywith) + StrLen(gPrefsR.notifywith) + 1;

                if ( StrLen(r.fields[note]) < (p - r.fields[note]) ) break;
            }
            else {
                p = r.fields[whichField];
            }

            hdField = MemPtrNew(StrLen(r.fields[whichField]) - (p - r.fields[whichField])+1);
            SysCopyStringResource(gAppErrStr, NotEnoughMemoryString);
            ErrFatalDisplayIf(!hdField, gAppErrStr);

            p = StrCopy(hdField, p);

            if (whichField == note &&
                    (end = StrStr(p, gPrefsR.notifywith))) {
                // end delimeter
                //
                *end = 0;
            }

            while ((q = StrChr(p, '\n'))) {
                // multiple event
                //

                *q = 0;
                if (AnalizeOneRecord(addrattr, p, &hd, &ignore))
                    goto Update_ErrHandler;
                p = q+1;

                // restore the saved name
                hd.name1 = name1;
                hd.name2 = name2;

                // reset multiple flag
                hd.flag.bits.multiple_event = 0;

                while (*p == ' ' || *p == '\t' || *p == '\n')
                    p++;     // skip white space
            }
            // last record
            if (*p) {
                // check the null '\n'
                if (AnalizeOneRecord(addrattr, p, &hd, &ignore))
                    goto Update_ErrHandler;
            }

            if (whichField == gHappyDaysField  // next is note field
                    && (gPrefsR.scannote     // scanNote & exists
                        && r.fields[note]
                        && StrStr(r.fields[note], gPrefsR.notifywith)) ) {
                whichField = note;
            }
            else whichField = -1;

            MemPtrFree(hdField);
        }
        MemHandleUnlock(recordH);
        currIndex++;
    }
    if (recordNum > 50) displayNextIndicate( INDICATE_NUM -1);

    return true;

Update_ErrHandler:
    MemPtrFree(hdField);
    MemHandleUnlock(recordH);
    return false;
}