Exemple #1
0
UInt16
CourseNewID(DmOpenRef cats, UInt16 category)
{
  Err err=errNone;
  MemHandle m;
  UInt16 index=0,lastid=0;

  err = DmSeekRecordInCategory(cats, &index, 0, dmSeekForward, category);
  if (err != errNone) return 0;

  while ((m = DmQueryNextInCategory(cats, &index, category))) {
    Char *s = MemHandleLock(m);
    if (s[0] == TYPE_COURSE) {
      CourseDBRecord c;
      UnpackCourse(&c, s);

      if (c.id > lastid) lastid = c.id;

    }
    index += 1;
    MemHandleUnlock(m);
  }

  // lastid contains the last existing ID here, so return lastid+1 to get the first
  // non-existing one
  return lastid+1;
}
Exemple #2
0
static void
CourseNameCacheLoad(CacheID id, UInt16 *ids, Char **values, UInt16 numItems)
{
  MemHandle m; 
  UInt16 index=0, i=0;
  
  while ((i < numItems) && ((m = DmQueryNextInCategory(DatabaseGetRef(), &index, DatabaseGetCat())) != NULL)) {
    Char *s=(Char *)MemHandleLock(m);
    if (s[0] == TYPE_COURSE) {
      CourseDBRecord c;
      Char *tempString;

      UnpackCourse(&c, s);
      
      tempString=(Char *)MemPtrNew(StrLen(c.name)+1);
      MemSet(tempString, MemPtrSize(tempString), 0);
      StrCopy(tempString, c.name);

      ids[i] = c.id;
      values[i] = tempString;
      i += 1;
    }
    MemHandleUnlock(m);
    index += 1;
  }
}
Exemple #3
0
/*****************************************************************************
* Function: GadgetDrawHintNext
* Complexity: O(N), N = DmNumRecords
*
* Description: Draw info for closest upcoming event.
*****************************************************************************/
void
GadgetDrawHintNext(void)
{
  MemHandle m;
  UInt16 index=0;
  DateTimeType dt;
  Boolean found=false, foundFirst=false;
  UInt16 curTime, curMinTind=0, wantCourse=0, curMinTime=0xFFFF;
  Int16 diffTime;
  TimeDBRecord *t;

  TimSecondsToDateTime(TimGetSeconds(), &dt);

  if ((dt.weekDay > 0) && (dt.weekDay <= gGadgetDaysNum)) {
    dt.weekDay = dt.weekDay-1;
  } else {
    dt.weekDay = 0;
    dt.hour = 0;
    dt.minute = 0;
  }

  curTime = dt.weekDay * GADGET_DAYVALUE + dt.hour * 60 + dt.minute;

  // Search for record nearest in _past_ to current time
  // NOTE: We assume that the types are sorted "times -> courses"! We use that to reduce everything to ONE while loop
  while( !found && ((m = DmQueryNextInCategory(DatabaseGetRef(), &index, DatabaseGetCat())) != NULL)) {
    Char *s=MemHandleLock(m);
    if (s[0] == TYPE_TIME) {
      t = (TimeDBRecord *)s;
      if ( GadgetEventIsVisible(t) ) {
        if (! foundFirst) {
          foundFirst = true;
          curMinTind = index;
          wantCourse = t->course;
        }

        diffTime = (t->day * GADGET_DAYVALUE + t->begin.hours * 60 + t->begin.minutes) - curTime;
        if ( (diffTime > 0) && (diffTime < curMinTime) ) {
          curMinTind = index;
          curMinTime = diffTime;
          wantCourse = t->course;
        }
      }
    } else if (s[0] == TYPE_COURSE) {
      CourseDBRecord c;
      UnpackCourse(&c, s);
      if (c.id == wantCourse) {
        gCourseIndex = index;
        gTimeIndex = curMinTind;
        found=true;
      }
    }
    MemHandleUnlock(m);
    index += 1;
  }

  if (! found || ! foundFirst)  GadgetDrawHintErase();
  else                          GadgetDrawHintCurrent();

}
Exemple #4
0
/*****************************************************************************
* Function:  CountCourses
*
* Description: Counts the courses saved in the given current category.
* Assumptions: This functions assumes, that the Records are SORTED with the
*              courses first and then the times.
*****************************************************************************/
UInt16
CountCourses(void)
{
  MemHandle m;
  UInt16 index=0,count=0;

  while ((m = DmQueryNextInCategory(DatabaseGetRefN(DB_MAIN), &index, DatabaseGetCat()))) {
    Char *s = MemHandleLock(m);
    if (s[0] == TYPE_COURSE) count += 1;
    MemHandleUnlock(m);
    index += 1;
  }

  return count;
}
void CleanupHappyDaysCache(DmOpenRef dbP)
{
    UInt16 currindex = 0;     
    MemHandle recordH = 0;

    if (dbP) {
        while (1) {
            recordH = DmQueryNextInCategory(dbP, &currindex,
                                            dmAllCategories);
            if (!recordH) break;
            
            DmRemoveRecord(dbP, currindex);     // remove all traces
        }
    }
}
/***********************************************************************
 *
 * FUNCTION:    ThumbnailDetailViewLoadGadgets
 *
 * DESCRIPTION: This routine loads sketches into the thumbnail view form
 *              thumbnail gadgets.
 *
 * PARAMETERS:  recordNum index of the first record to display.
 *
 * RETURNED:    nothing
 *
 ***********************************************************************/
static void ThumbnailDetailViewLoadGadgets(FormType* frm) {
  UInt16 row;
  MemHandle recordH;
  DynamicButtonType* btnThumb, *btnName, *btnNameMasked, *btnAlarm;
  MemPtr ptr;
  UInt16 attr;
  Char* record_name, *record_note;
  DiddleBugRecordType record;
  FontID font;
  UInt32 alarmSecs;
  UInt16 recordNum = d.top_visible_record;
  const UInt16 max = Min(recordsPerPage, d.records_in_cat - d.top_row_pos_in_cat);
  Boolean private = false;

  for (row = 0; row < max; row++) {
    /* Get the next record in the current category. */
    recordH = DmQueryNextInCategory (d.dbR, &recordNum, p.category);

    if(row == 0) {
      /* store the position of the first row so we can use */
      /* d.top_row_pos_in_cat+row when drawing             */
      d.top_row_pos_in_cat = recordH ? DmPositionInCategory(d.dbR, recordNum, p.category) : 0;
    }

    btnThumb = (DynamicButtonType*) FrmGetGadgetData(frm, FrmGetObjectIndex(frm, Thumb1 + row));
    btnName = (DynamicButtonType*) FrmGetGadgetData(frm, FrmGetObjectIndex(frm, Thumb1Name + row));
    btnNameMasked = (DynamicButtonType*) FrmGetGadgetData(frm, FrmGetObjectIndex(frm, Thumb1NameMasked + row));
    btnAlarm = (DynamicButtonType*) FrmGetGadgetData(frm, FrmGetObjectIndex(frm, Thumb1Alarm + row));

    /* Store record number */
    btnThumb->value = recordNum;
    btnName->value = recordNum;
    btnNameMasked->value = recordNum;
    btnAlarm->value = recordNum;

    /* Clear old internal values */
    btnThumb->selected = false;

    /* Read record attributes */
    DmRecordInfo(d.dbR, recordNum, &attr, NULL, NULL);
    private = attr & dmRecAttrSecret && d.privateRecordStatus == maskPrivateRecords;
    
    /* Get a pointer to the record */
    ptr = MemHandleLock(recordH);

    if (private) {
      DrawMaskedRecord(btnThumb->content.bmpW, maskPattern);
    } else {
Exemple #7
0
Boolean
CourseGetIndex(DmOpenRef cats, UInt16 category, UInt16 courseID, UInt16 *index)
{
  MemHandle m;

  *index = 0;
  
  while ((m = DmQueryNextInCategory(cats, index, category)) != NULL) {
    Char *s=(Char *)MemHandleLock(m);
    if (s[0] == TYPE_COURSE) {
      CourseDBRecord c;
      UnpackCourse(&c, s);
      if (c.id == courseID) {
        // Found it!
        MemHandleUnlock(m);
        return true;
      }
    }
    MemHandleUnlock(m);
    *index += 1;
  }

  return false;
}
Exemple #8
0
/***********************************************************************
 *
 * FUNCTION:    ApptFindFirst
 *
 * DESCRIPTION: This routine finds the first appointment on the specified
 *              day.
 *
 * PARAMETERS:  dbP    - pointer to the database
 *              date   - date to search for
 *              indexP - pointer to the index of the first record on the 
 *                       specified day (returned value)
 *
 * RETURNED:    true if a record has found
 *
 * REVISION HISTORY:
 *          Name    Date        Description
 *          ----    ----        -----------
 *          art 6/15/95     Initial Revision
 *
 ***********************************************************************/
Boolean ApptFindFirst (DmOpenRef dbP, DateType date, UInt16 * indexP) {
    Err err;
    Int16 numOfRecords;
    Int16 kmin, probe, i;     // all positions in the database.
    Int16 result = 0;         // result of comparing two records
    UInt16 index;
    MemHandle recordH;
    Boolean found = false;
    ApptPackedDBRecordPtr r;

    kmin = probe = 0;
    numOfRecords = DmNumRecords(dbP);


    while (numOfRecords > 0) {
        i = numOfRecords >> 1;
        probe = kmin + i;

        index = probe;
        recordH = DmQueryNextInCategory (dbP, &index, dmAllCategories);
        if (recordH) {
            r = (ApptPackedDBRecordPtr) MemHandleLock (recordH);
            if (r->flags.repeat)
                result = 1;
            else
                result = DateCompare (date, r->when.date);
            MemHandleUnlock (recordH);
        }

        // If no handle, assume the record is deleted, deleted records
        // are greater.
        else
            result = -1;


        // If the date passed is less than the probe's date, keep searching.
        if (result < 0)
            numOfRecords = i;

        // If the date passed is greater than the probe's date, keep searching.
        else if (result > 0) {
            kmin = probe + 1;
            numOfRecords = numOfRecords - i - 1;
        }

        // If the records are equal find the first record on the day.
        else {
            found = true;
            *indexP = index;
            while (true) {
                err = DmSeekRecordInCategory (dbP, &index, 1, dmSeekBackward,
                                              dmAllCategories);
                if (err == dmErrSeekFailed) break;

                recordH = DmQueryRecord(dbP, index);
                r = (ApptPackedDBRecordPtr) MemHandleLock (recordH);
                if (r->flags.repeat)
                    result = 1;
                else
                    result = DateCompare (date, r->when.date);
                MemHandleUnlock (recordH);
                if (result != 0) break;
                *indexP = index;
            }

            break;
        }
    }


    // If that were no appointments on the specified day, return the
    // index of the next appointment (on a future day).
    if (! found) {
        if (result < 0)
            *indexP = probe;
        else
            *indexP = probe + 1;
    }

    return (found);
}
Exemple #9
0
UInt16
CourseListGen(Char **itemList, UInt16 *courseID, UInt16 *courseInd, UInt16 numItems, UInt16 curInd, UInt8 searchFor)
{
  UInt16 index=0, i=0, rv=0;
  MemHandle m;
  UInt16 *tmpCourseInd=NULL;

  if (courseInd == NULL)
    tmpCourseInd = (UInt16 *)MemPtrNew(numItems * sizeof(UInt16));

  while((i < numItems) && ((m = DmQueryNextInCategory(DatabaseGetRef(), &index, DatabaseGetCat())) != NULL)) {
    Char *s=(Char *)MemHandleLock(m);
    if (s[0] == TYPE_COURSE) {
      UInt16 j;
      CourseDBRecord c;
      Char *tempString;
      MemHandle shortType=MemHandleNew(1);

      UnpackCourse(&c, s);

      tempString=(Char *)MemPtrNew(StrLen(c.name)+3+StrLen(c.teacherName)+CTYPE_SHORT_MAXLENGTH+CTYPE_ADD_MAXLENGTH+1);
      CourseTypeGetShort(&shortType, c.ctype);
      // StrPrintF(shortType, "T");
      StrPrintF(tempString, "%s (%s) [%s]", c.name, c.teacherName, (Char *)MemHandleLock(shortType));
      MemHandleUnlock(shortType);
      MemHandleFree(shortType);

      // Do a nice insertion sort here. DatAlg MUST have been good for something :-)
      j = i;
      while ( (j > 0) && (StrCompare(itemList[j-1], tempString) > 0) ) {
        itemList[j] = itemList[j-1];
        if (courseInd != NULL)  courseInd[j]=courseInd[j-1];
        else                    tmpCourseInd[j]=tmpCourseInd[j-1];
        if (courseID != NULL)  courseID[j]=courseID[j-1];
        j -= 1;
      }
 
      itemList[j]=tempString;
      if (courseInd != NULL)  courseInd[j]=index;
      else                    tmpCourseInd[j]=index;
      if (courseID != NULL)  courseID[j]=c.id;


      i += 1;
    }
    MemHandleUnlock(m);
    index += 1;
  }

  // We iterate through all to get the item to be selected
  // We could do that in the loop above, but we would need
  // a) to mess with insertion sort (make it slow)
  // b) to make the code ugly at two points
  // c) We don't care since we expect about 20 courses, that's nothing to iterate...
  // We implement the loop multiple times (once for each search type, last param)
  // so that we do not need a condition inside the loop for every run
  i = 0;

  if (searchFor == CLIST_SEARCH_INDEX) {
    while (! rv && (i < numItems)) {
      if (courseInd == NULL) {
        if (tmpCourseInd[i] == curInd)  rv = i;
      } else {
        if (courseInd[i] == curInd)  rv = i;
      }
      i += 1;
    }
  } else if ((searchFor == CLIST_SEARCH_ID) && (courseID != NULL)) {
    while (! rv && (i < numItems)) {
      if (courseID[i] == curInd)  rv = i;
      i += 1;
    }
  }

  if (tmpCourseInd != NULL)
    MemPtrFree((MemPtr)tmpCourseInd);

  return rv;
}
Exemple #10
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;
}
Exemple #11
0
/*------------------------------------------------------CIRexxApp::FindLaunch-+
|                                                                             |
+----------------------------------------------------------------------------*/
Err CIRexxApp::FindLaunch(FindParamsPtr pFindParams)
{
   //<<<JAL TODO: This is currently dependent on the Rexx category.
   //             I'm not sure if we'll ever need to change/add-to this,
   //             but if we do, then this code will have to be changed
   //             along with the GoTo command.
   Err err;
   LocalID dbID;
   UInt16 cardNo = 0;
   DmOpenRef dbP;
   DmSearchStateType searchState;
   UInt16 recordNum;
   MemHandle hRecord;
   UInt32 pos;
   UInt16 matchLength;
   Boolean match, full;
   RectangleType r;
   UInt32 type;
   UInt32 creator;

   // Open our database (should we search MemoPad and pedit, too?)
   // and do our Find.  We define the semantics of Find, so
   // instead of searching the whole records for the search string,
   // let's just search for scripts with the search string as their "name."
   if (FindDrawHeader(pFindParams, "Rexx Scripts")) {
      goto m_return;
   }
   if ((err = DmGetNextDatabaseByTypeCreator(
       true, &searchState, 'data', CREATORID, true, &cardNo, &dbID)) != errNone) {
      pFindParams->more = false;
      return errNone;
   }
   if ((err = DmDatabaseInfo(0, dbID, 0, 0, 0, 0, 0, 0, 0, 0, 0, &type, &creator)) != errNone ||
      (type != 'data' && creator != CREATORID)) {
      pFindParams->more = false;
      return errNone;
   }
   if ((dbP = DmOpenDatabase(cardNo, dbID, pFindParams->dbAccesMode)) == 0 || 
      DmGetAppInfoID(dbP) == 0) { /* if categories not initialized then CategoryGetName throws fatal error */ 
      pFindParams->more = false;
      return errNone;
   }
   UInt16 category;
   char categoryName[dmCategoryLength];
   for (category = 0; category < dmRecNumCategories; ++category) {
       CategoryGetName(dbP, category, categoryName);
       if (!StrCaselessCompare(categoryName, "REXX")) { break; }
   }
   if (category == dmRecNumCategories) { goto m_return; }
   // set it to dmAllCategories?

   UInt32 romVersion;
   FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);

   full = false;
   recordNum = pFindParams->recordNum;
   while (true) {

      // Because applications can take a long time to finish a Find when
      // the result may already be on the screen, or for other reasons,
      // users like to be able to stop the Find.  So, stop it if any event
      // is pending, i.e., if the user does something with the device.
      // Because actually checking if an event is pending slows the
      // search itself, just check it every so many records.
      if ((recordNum & 0x000f) == 0 && EvtSysEventAvail(true)) {
         pFindParams->more = true;
         break;
      }
      if (!(hRecord = DmQueryNextInCategory(dbP, &recordNum, category))) {
         pFindParams->more = false;
         break;
      }

      Char * p = (char *)MemHandleLock(hRecord);
      UInt32 isInternational;
      err = FtrGet(sysFtrCreator, sysFtrNumIntlMgr, &isInternational);
      if (err == errNone && isInternational) {
         match = TxtFindString(p, pFindParams->strToFind, &pos, &matchLength);
      } else {
         match = TxtGlueFindString(p, pFindParams->strToFind, &pos, &matchLength);
      }
      if (match) {
         // Add the match to the find paramter block.
         // If there is no room to display the match
         // then the following function will return true.
         full = FindSaveMatch(pFindParams, recordNum, (UInt16)pos, 0, 0, cardNo, dbID);
         if (!full) {
            // Get the bounds of the region where we will draw the results, and
            // display the title of the description neatly in that area.
            FindGetLineBounds(pFindParams, &r);
            Int16 x = r.topLeft.x + 1;
            Int16 y = r.topLeft.y;
            Int16 w = r.extent.x - 2;
            Char * cr = StrChr(p, linefeedChr);
            UInt16 titleLen = (cr == 0)? StrLen(p) : cr - p;
            Int16 fntWidthToOffset;
            if (romVersion >= sysMakeROMVersion(3, 1, 0, sysROMStageRelease, 0)) {
               fntWidthToOffset = FntWidthToOffset(p, titleLen, w, 0, 0);
            } else {
               fntWidthToOffset = FntGlueWidthToOffset(p, titleLen, w, 0, 0);
            }
            if (fntWidthToOffset == titleLen) {
               WinDrawChars(p, titleLen, x, y);
            } else {
               Int16 titleWidth;
               titleLen = FntWidthToOffset(p, titleLen, w - FntCharWidth(chrEllipsis), 0, &titleWidth);
               WinDrawChars(p, titleLen, x, y);
               WinDrawChar (chrEllipsis, x + titleWidth, y);
            }
            ++pFindParams->lineNumber;
         }
      }
      MemHandleUnlock(hRecord);
      if (full) { break; }
      ++recordNum;
   }

m_return:
   DmCloseDatabase(dbP);
   return errNone;
}
Exemple #12
0
/*****************************************************************************
* Function: GadgetDrawEvents
*
* Description: Draws all events, used by GadgetRedraw and GadgetDrawComplete
*****************************************************************************/
void
GadgetDrawEvents()
{
  UInt8 pos = 0;
  UInt8 num_times = 0;
  UInt16 index=0, time_index;
  MemHandle m, ml; // ml = memhandle for look-ahead, would have to be an array for >2 MAX_AT_A_TIME
  TimeDBRecord *t = NULL;
  TimeDBRecord *tl = NULL; // look_ahead time

  UInt8 last_day = 0;
  UInt16 last_begin = 0, last_end = 0;
  UInt8 last_pos = 0;
  
  TNlistFree(gGadgetTimeList);
  gGadgetTimeList = NULL;

  ml = DmQueryNextInCategory(DatabaseGetRef(), &index, DatabaseGetCat());

  while( ml != NULL ) {

    Boolean look_ahead_not_visible = true;

    m = ml;
    time_index = index;
    t=(TimeDBRecord *)MemHandleLock(m);

    while (look_ahead_not_visible) {
      index += 1;
      ml = DmQueryNextInCategory(DatabaseGetRef(), &index, DatabaseGetCat());

      if (ml != NULL) {
	tl = (TimeDBRecord *)MemHandleLock(ml);
	if ( (tl->type == TYPE_TIME) && GadgetEventIsVisible(tl) ) {
	  look_ahead_not_visible = false;
	} else {
	  MemHandleUnlock(ml);
	  ml = NULL;
	  tl = NULL;
	}
      } else {
	break;
      }
    }

    if ((t->type == TYPE_TIME) && GadgetEventIsVisible(t) ) {

      RGBColorType c;
      GadgetTimeListType *gtl;
      UInt16 current_begin, current_end;

      current_begin = TimeToInt(t->begin);
      current_end = TimeToInt(t->end);

      // How many entries?
      if ( GadgetEventTimesCollide(last_day, last_begin, last_end,
				   t->day, current_begin, current_end) ) {
	// we collide with previous event, draw right
	if (last_pos == 0) {
	  pos = 1;
	} else {
	  pos = 0;
	}
	if (last_end < current_end) {
	  last_begin = current_begin;
	  last_end = current_end;
	  last_day = t->day;
	  last_pos = pos;
	}
	num_times = 2;
      } else {
	// We do not collide with last event, check if we collide with next event
	if ( (tl != NULL) && (tl->type == TYPE_TIME) && GadgetEventsCollide(t, tl) ) {
	  // Next event is visible and collides with current event 
	  last_begin = current_begin;
	  last_end = current_end;
	  last_day = t->day;
	  num_times = 2;
	  pos = 0;
	  last_pos = pos;
	} else {
	  // We do not collide with previous or next event => no collision
	  last_begin = TimeToInt(t->begin);
	  last_end = TimeToInt(t->end);
	  last_day = t->day;
	  num_times = 1;
	  pos = 0;	  
	  last_pos = pos;
	}
      }


      c.r=t->color[0];
      c.g=t->color[1];
      c.b=t->color[2];

      gtl = (GadgetTimeListType *)MemPtrNew(sizeof(GadgetTimeListType));
      gtl->index = time_index;
      gtl->num = num_times;
      gtl->pos = pos;
      GadgetTimeSetRect(&(gtl->rect), (TimeType)t->begin, (TimeType)t->end, t->day, num_times, pos);

      gGadgetTimeList = TNlistAppend(gGadgetTimeList, gtl);

      GadgetDrawTime((TimeType)t->begin, (TimeType)t->end, t->day, &c, t->course, num_times, pos);

    }
    MemHandleUnlock(m);
    if (ml != NULL) {
      MemHandleUnlock(ml);
      tl = NULL;
    }
  }
}
Exemple #13
0
/*****************************************************************************
* Function: GadgetTap
*
* Description: Handles penDown events (taps) on the gadget
*****************************************************************************/
void
GadgetTap(FormGadgetType *pGadget, EventType *event)
{
  //you may find it useful to track if they
  //lift the pen still within the boundaries of the gadget
  Boolean isPenDown = true;
  Int16 newPointX, newPointY, startPointX, startPointY;
  UInt16 index;
  RectangleType bounds;

  // This is just needed since we do not want to access internal structure
  // data directly in FormGadgetType (need rect field below)
  index = TNGetObjectIndexFromPtr(FrmGetActiveForm(), pGadget);
  FrmGetObjectBounds(FrmGetActiveForm(), index, &bounds);

  //track the pen down event
  EvtGetPen(&newPointX, &newPointY, &isPenDown);
  startPointX = newPointX;
  startPointY = newPointY;
  while (isPenDown){
    EvtGetPen(&newPointX, &newPointY, &isPenDown);
  }

  if (RctPtInRectangle(newPointX, newPointY, &bounds)) {
    /* the pen up was also in the gadget
       This can mean two things:
       1) we got a strike command
       2) a field was tapped
    */
    RectangleType topRight, bottomRight;
    Boolean found=false, foundTime=false;
    MemHandle m;
    TimeDBRecord *t;
    UInt16 index=0, wantCourse=0, tmp3_4th=0;
    GadgetTimeListType *gtl;
    TNlist *tmpl;

    /* Check for stroke commands */

    tmp3_4th = (3 * bounds.extent.x) / 4;
    RctSetRectangle(&topRight,
                    bounds.topLeft.x+ tmp3_4th,
                    bounds.topLeft.y,
                    bounds.extent.x - tmp3_4th,
                    bounds.extent.y/2
                   );
    RctSetRectangle(&bottomRight,
                    bounds.topLeft.x + tmp3_4th,
                    bounds.topLeft.y + (bounds.extent.y/2),
                    bounds.extent.x - tmp3_4th,
                    bounds.extent.y / 2
                   );

    if (RctPtInRectangle(startPointX, startPointY, &bottomRight) &&
        RctPtInRectangle(newPointX, newPointY, &topRight) ) {
      // Stroke Command: BACK
      GadgetDrawStep(winUp);
      return;
    } else if (RctPtInRectangle(startPointX, startPointY, &topRight) &&
               RctPtInRectangle(newPointX, newPointY, &bottomRight) ) {
      // Stroke Command: NEXT
      GadgetDrawStep(winDown);
      return;
    }


    tmpl = gGadgetTimeList;
    while (tmpl != NULL) {
      gtl = (GadgetTimeListType *)tmpl->data;
      if (RctPtInRectangle(newPointX, newPointY, &(gtl->rect))) {
	m = DmQueryRecord(DatabaseGetRef(), gtl->index);
        if (m) {
          // mt may be null, for example if next is drawn after delete!
          t = (TimeDBRecord *)MemHandleLock(m);

	  // we got a match
	  wantCourse = t->course;
	  gTimeIndex = gtl->index;
	  foundTime  = true;

	  MemHandleUnlock(m);
	}
      }
      tmpl = tmpl->next;
    }

    // Search for the clicked time
    if (foundTime) {
      index = 0;
      while(! found && ((m = DmQueryNextInCategory(DatabaseGetRef(), &index, DatabaseGetCat())) != NULL)) {
	Char *s = (Char *)MemHandleLock(m);
	if (s[0] == TYPE_COURSE) {
	  CourseDBRecord c;
	  UnpackCourse(&c, s);
	  if (c.id == wantCourse) {
	    SndPlaySystemSound(sndClick);
	    gCourseIndex = index;
	    found=true;
	  }
	}
	MemHandleUnlock(m);
	index += 1;
      }
    }

    if (found && foundTime) {
      GadgetDrawHintCurrent();
    } else {
      SndPlaySystemSound(sndError);
    }

  } // else outside gadget bounds -> do nothing

}
Exemple #14
0
/*****************************************************************************
* Function: GadgetDrawStep
*
* Description: Helper function for GadgetTap. Highlights next of previous
*              event on current screen
*****************************************************************************/
void
GadgetDrawStep(WinDirectionType direction)
{
  MemHandle m;
  UInt16 index=gTimeIndex, wantCourse=0, courseIndex=0;
  Boolean found=false, endLoop=false;
  TimeDBRecord *t=NULL;

  /* ASSUMPTION: We assume that the user does not have 2^16 events
   * in his schedule. Otherwise this can become an endless. loop. but
   * since I think this is a reasonable assumption I will not take any
   * special care for this...
   * If we loop to ID 2^16-1 we will surely find no record and terminate
   * below (m = ... == NULL)
   */

  
  if ( (direction == winUp) && (index > 0) ) {
    while( !endLoop && (DmSeekRecordInCategory(DatabaseGetRefN(DB_MAIN), &index, 1, dmSeekBackward, DatabaseGetCat()) == errNone)) {
      Char *s;
      m = DmQueryRecord(DatabaseGetRefN(DB_MAIN), index);
      s=MemHandleLock(m);
      if (s[0] == TYPE_TIME) {
        t = (TimeDBRecord *)s;
        if ( GadgetEventIsVisible(t) ) {
          // Found entry
          endLoop=true;
          found = true;
          wantCourse = t->course;
        }
      } else {
        // nothing more to search and nothing found
        endLoop=true;
      }
      MemHandleUnlock(m);
    }
  } else if (direction == winDown) {
    index += 1;
    while( !endLoop && ((m = DmQueryNextInCategory(DatabaseGetRef(), &index, DatabaseGetCat())) != NULL)) {
      Char *s=MemHandleLock(m);
      if (s[0] == TYPE_TIME) {
        t = (TimeDBRecord *)s;
        if ( GadgetEventIsVisible(t) ) {
          // Found entry
          endLoop=true;
          found = true;
          wantCourse = t->course;
        } else {
          // previous in DB is not visible, search further
          index += 1;
        }
      } else {
        // nothing more to search and nothing found
        endLoop=true;
      }
      MemHandleUnlock(m);
    }
  }
  if (found && CourseGetIndex(DatabaseGetRef(), DatabaseGetCat(), wantCourse, &courseIndex)) {
    GadgetSetHintCourseIndex(courseIndex);
    GadgetSetHintTimeIndex(index);
    GadgetDrawHintCurrent();
  }
}
Exemple #15
0
/***********************************************************************
 *
 * FUNCTION:    ApptGetAppointments
 *
 * DESCRIPTION: This routine returns a list of appointments that are on 
 *              the date specified
 *
 * PARAMETERS:  dbP    - pointer to the database
 *              date   - date to search for
 *              countP - number of appointments on the specified 
 *                       day (returned value)
 *
 * RETURNED:    handle of the appointment list (ApptInfoType)
 *
 * REVISION HISTORY:
 *          Name    Date        Description
 *          ----    ----        -----------
 *          art     6/15/95     Initial Revision
 *
 ***********************************************************************/
MemHandle ApptGetAppointments (DmOpenRef dbP, DateType date, UInt16 * countP) {
    Err error;
    Int16 result;
    Int16 count = 0;
    UInt16    recordNum;
    Boolean repeats;
    MemHandle recordH;
    MemHandle apptListH;
    ApptInfoPtr apptList;
    ApptDBRecordType apptRec;
    ApptPackedDBRecordPtr r;

    // Allocated a block to hold the appointment list.
    apptListH = MemHandleNew (sizeof (ApptInfoType) * apptMaxPerDay);
    ErrFatalDisplayIf(!apptListH, "Out of memory");
    if (! apptListH) return (0);

    apptList = MemHandleLock (apptListH);

    // Find the first non-repeating appointment of the day.
    if (ApptFindFirst (dbP, date, &recordNum)) {
        while (count < apptMaxPerDay) {
            // Check if the appointment is on the date passed, if it is
            // add it to the appointment list.
            recordH = DmQueryRecord (dbP, recordNum);
            r = MemHandleLock (recordH);
            result = DateCompare (r->when.date, date);

            if (result == 0) {
                // Add the record to the appoitment list.
                apptList[count].startTime = r->when.startTime;
                apptList[count].endTime = r->when.endTime;
                apptList[count].recordNum = recordNum;
                count++;
            }
            MemHandleUnlock (recordH);
            if (result != 0) break;

            // Get the next record.
            error = DmSeekRecordInCategory (dbP, &recordNum, 1,
                                            dmSeekForward,
                                            dmAllCategories);
            if (error == dmErrSeekFailed) break;
        }
    }

    // Add the repeating appointments to the list.  Repeating appointments
    // are stored at the beginning of the database.
    recordNum = 0;
    while (count < apptMaxPerDay) {
        recordH = DmQueryNextInCategory (dbP, &recordNum, dmAllCategories);
        if (! recordH) break;
        
        r = (ApptPackedDBRecordPtr) MemHandleLock (recordH);
        
        repeats = (r->flags.repeat != 0);
        if (repeats) {
            ApptUnpack (r, &apptRec);
            if (ApptRepeatsOnDate (&apptRec, date)) {
                // Add the record to the appoitment list.
                apptList[count].startTime = r->when.startTime;              
                apptList[count].endTime = r->when.endTime;              
                apptList[count].recordNum = recordNum;  
                count++;
            }
        }
        MemHandleUnlock (recordH);

        // If the record has no repeating info we've reached the end of the 
        // repeating appointments.
        if (! repeats) break;
        
        recordNum++;
    }

    // Sort the list by start time.
    // SysInsertionSort (apptList, count, sizeof (ApptInfoType),
    //          ApptListCompare, 0L);

    // If there are no appointments on the specified day, free the appointment
    // list.
    if (count == 0) {
        MemPtrFree (apptList);
        apptListH = 0;
    }
    // Resize the appointment list block to release any unused space.
    else {
        MemHandleUnlock (apptListH);
        MemHandleResize (apptListH, count * sizeof (ApptInfoType));
    }

    *countP = count;
    return (apptListH);
}
Exemple #16
0
static void
ExamsTableInit(void)
{
  TableType *table=GetObjectPtr(TABLE_exams);
  UInt16 i, j;
  MemHandle m;
  UInt16 index=0;

  gExamsSelRow = 0;  
  
  for (i=0; i < TblGetNumberOfRows(table); ++i) {
    TblSetItemStyle(table, i, EXCOL_DONE, checkboxTableItem);
    TblSetItemStyle(table, i, EXCOL_COURSE, customTableItem);
    TblSetItemStyle(table, i, EXCOL_NOTE, customTableItem);
    TblSetItemStyle(table, i, EXCOL_DATE, customTableItem);
    TblSetItemStyle(table, i, EXCOL_TIME, customTableItem);
    TblSetItemStyle(table, i, EXCOL_SELI, customTableItem);
  }

  TblSetColumnSpacing(table, EXCOL_DONE, 2);
  TblSetColumnSpacing(table, EXCOL_COURSE, 1);
  TblSetColumnSpacing(table, EXCOL_NOTE, 3);
  TblSetColumnSpacing(table, EXCOL_DATE, 1);
  TblSetColumnSpacing(table, EXCOL_TIME, 3);

  TblSetColumnUsable(table, EXCOL_DONE, true);
  TblSetColumnUsable(table, EXCOL_COURSE, true);
  TblSetColumnUsable(table, EXCOL_NOTE, true);
  TblSetColumnUsable(table, EXCOL_DATE, true);
  TblSetColumnUsable(table, EXCOL_TIME, true);
  TblSetColumnUsable(table, EXCOL_SELI, true);

  for (i=0; i < TblGetNumberOfRows(table); ++i) {
    TblSetRowUsable(table, i, false);
  }

  TblSetCustomDrawProcedure(table, EXCOL_COURSE, TableDrawData);
  TblSetCustomDrawProcedure(table, EXCOL_NOTE, TableDrawData);
  TblSetCustomDrawProcedure(table, EXCOL_DATE, TableDrawData);
  TblSetCustomDrawProcedure(table, EXCOL_TIME, TableDrawData);
  TblSetCustomDrawProcedure(table, EXCOL_SELI, TableDrawSelection);

  i = 0; j = 0;
  while ((i < EX_MAX_ROWS) && (m = DmQueryNextInCategory(DatabaseGetRefN(DB_MAIN), &index, DatabaseGetCat()))) {
    UInt32 uid=0;
    ExamDBRecord *ex;

    DmRecordInfo(DatabaseGetRefN(DB_MAIN), index, NULL, &uid, NULL);
    ex = MemHandleLock(m);
    if (ex->type == TYPE_EXAM) {
      // We have an exam, insert if above current offset
      if (j >= gExamsOffset) {
        UInt16 done = ex->flags & EX_FLAG_DONE;
        TblInsertRow(table, i);
        TblSetRowID(table, i, index);
        TblSetRowData(table, i, uid);
        if (uid == gExamsLastSelRowUID)  gExamsSelRow = i;
        TblSetRowUsable(table, i, true);
        TblMarkRowInvalid(table, i);
        TblSetItemInt(table, i, EXCOL_DONE, done);
        i += 1;
      }
      j += 1;
    }
    MemHandleUnlock(m);
    index += 1;
  }

  // Check if there are displayed exams. If there are not, hide the
  // buttons for edit/delete/beam, otherwise show
  if (i > 0) {
    CtlShowControl(GetObjectPtr(BUTTON_ex_edit));
    CtlShowControl(GetObjectPtr(BUTTON_ex_del));
    CtlShowControl(GetObjectPtr(BUTTON_ex_beam));
    CtlShowControl(GetObjectPtr(BUTTON_ex_note));
  } else {
    CtlHideControl(GetObjectPtr(BUTTON_ex_edit));
    CtlHideControl(GetObjectPtr(BUTTON_ex_del));
    CtlHideControl(GetObjectPtr(BUTTON_ex_beam));
    CtlHideControl(GetObjectPtr(BUTTON_ex_note));
  }

  // decide and (show/hide) whether to have enabled or disabled down button
  // There must be another record, otherwise our course we assigned this exam to would
  // not exist, that should never happen. But to cover my future mistakes
  // index has been increased one in the loop.
  if ( (m = DmQueryNextInCategory(DatabaseGetRefN(DB_MAIN), &index, DatabaseGetCat())) != NULL) {
    // We have more records, are there exams?
    Char *s;
    s = MemHandleLock(m);
    // Since the DB is sorted we do not need to search for exams but just check the next
    // record. If it is not an exam record there won't be any later!
    if (s[0] == TYPE_EXAM) {
      CtlHideControl(GetObjectPtr(REPEAT_ex_down_dis));
      CtlShowControl(GetObjectPtr(REPEAT_ex_down));
    } else {
      CtlHideControl(GetObjectPtr(REPEAT_ex_down));
      CtlShowControl(GetObjectPtr(REPEAT_ex_down_dis));
    }
    MemHandleUnlock(m);
  } else {
    CtlHideControl(GetObjectPtr(REPEAT_ex_down));
    CtlShowControl(GetObjectPtr(REPEAT_ex_down_dis));
  }

  // decide (and show/hide) whether to have enabled or disabled up button
  if (gExamsOffset > 0) {
    CtlHideControl(GetObjectPtr(REPEAT_ex_up_dis));
    CtlShowControl(GetObjectPtr(REPEAT_ex_up));
  } else {
    CtlHideControl(GetObjectPtr(REPEAT_ex_up));
    CtlShowControl(GetObjectPtr(REPEAT_ex_up_dis));
  }
}
Exemple #17
0
/***********************************************************************
 *
 * FUNCTION:    ThumbnailViewLoadGadgets
 *
 * DESCRIPTION: This routine loads sketches into the thumbnail view form
 *              thumbnail gadgets.
 *
 * PARAMETERS:  recordNum index of the first record to display.
 *
 * RETURNED:    nothing
 *
 ***********************************************************************/
static void ThumbnailViewLoadGadgets(FormType* frm) {
  UInt16 row;
  MemHandle recordH;
  DynamicButtonType* btn;
  MemPtr ptr;
  UInt16 attr;
  UInt16 recordNum = d.top_visible_record;
  const UInt16 max = Min(recordsPerPage, d.records_in_cat - d.top_row_pos_in_cat);

  for (row = 0; row < max; row++) {
    /* Get the next record in the current category. */
    recordH = DmQueryNextInCategory (d.dbR, &recordNum, p.category);

    if(row == 0) {
      /* store the position of the first row so we can use */
      /* d.top_row_pos_in_cat + row when drawing           */
      d.top_row_pos_in_cat = recordH ? DmPositionInCategory(d.dbR, recordNum, p.category) : 0;
    }

    btn = (DynamicButtonType*) FrmGetGadgetData(frm, FrmGetObjectIndex(frm, Thumb1 + row));

    /* Store record number */
    btn->value = recordNum;

    /* Clear old internal values */
    btn->selected = false;

    /* Read record attributes */
    DmRecordInfo(d.dbR, recordNum, &attr, NULL, NULL);

    if (attr & dmRecAttrSecret && d.privateRecordStatus == maskPrivateRecords) {
      DrawMaskedRecord(btn->content.bmpW, maskPattern);
    } else {
/*       WinHandle oldH = NULL; */
/*       Err err = 0; */
/*       BitmapType* bmp = BmpCreate(btn->contentRect.extent.x,  */
/*                btn->contentRect.extent.y, 1, NULL, &err); */
/*       if (err) abort(); */

      /* Uncompress thumbnail */
      ptr = MemHandleLock(recordH);
      //      MemMove(BmpGetBits(bmp), ptr + sketchDataOffset, sketchThumbnailSize);
      MemMove(BmpGetBits(WinGetBitmap(btn->content.bmpW)), ptr + sketchDataOffset, sketchThumbnailSize);
      MemHandleUnlock(recordH);

      /* Write thumbnail to content bitmap */
/*       WinPushDrawState(); */
/*       WinSetCoordinateSystem(kCoordinatesNative); */
/*       oldH = WinSetDrawWindow(btn->content.bmpW); */
/*       WinPaintBitmap(bmp, 0, 0); */
/*       WinSetDrawWindow(oldH); */
/*       WinPopDrawState(); */

      /* Clean up */
/*       BmpDelete(bmp); */
    }

    recordNum++;

    /* Show the right gadgets... */
    ShowObject(frm, Thumb1 + row);
  }

  /* ...store the index of the last visible thumbnail... */
  d.lastVisibleThumbnail = row - 1;

  /* ... and hide the rest */
  for (; row < recordsPerPage; row++)
    HideObject(frm, Thumb1 + row);

  /* Update the scroll arrows. */
  ThumbnailViewUpdateScrollers (frm);
}
Exemple #18
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;
}