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; }
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; } }
/***************************************************************************** * 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(); }
/***************************************************************************** * 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 {
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; }
/*********************************************************************** * * 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); }
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; }
/** * @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; }
/*------------------------------------------------------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; }
/***************************************************************************** * 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; } } }
/***************************************************************************** * 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 }
/***************************************************************************** * 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(); } }
/*********************************************************************** * * 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); }
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)); } }
/*********************************************************************** * * 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); }
/** * @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; }