/* ** Load the record data (flags, ...) - but not the picture */ static void LoadRecordData(void) { MemHandle t = NULL; MemPtr ptr = NULL; UInt16 attr = 0; UInt32 highDataOffset = 0; Int16 len = 0; PRINT("Loading Record Data for %hd", p.dbI); /* Clear unmasked flag */ d.unmaskedCurrentRecord = false; /* Open and lock the record */ t = DmQueryRecord(d.dbR, p.dbI); if (!t) abort(); ptr = MemHandleLock(t); /* Is the record private? */ DmRecordInfo(d.dbR, p.dbI, &attr, NULL, NULL); d.record_private = attr & dmRecAttrSecret; /* Read the header data */ MemMove(&d.record, ptr, sizeof(DiddleBugRecordType)); /* Read the additional alarm info */ highDataOffset = sketchDataOffset + d.record.sketchLength; len = StrLen((Char*)(ptr + highDataOffset)) + 1; /* +1 for null char */ if (d.record_name) MemHandleFree(d.record_name); d.record_name = MemHandleNew(len); ASSERT(d.record_name); MemMove(MemHandleLock(d.record_name), ptr + highDataOffset, len); MemHandleUnlock(d.record_name); highDataOffset += len; len = StrLen((Char*)(ptr + highDataOffset)) + 1; /* +1 for null char */ if (d.record_note) MemHandleFree(d.record_note); d.record_note = MemHandleNew(len); ASSERT(d.record_note); MemMove(MemHandleLock(d.record_note), ptr + highDataOffset, len); MemHandleUnlock(d.record_note); highDataOffset += len; /* Clear old data since there may not be an extra-data block yet */ MemSet(&d.record_sound, sizeof(AlarmSoundInfoType), 0); d.record_sound.listIndex = -1; /* default */ /* Read new extra-data (if it exists and is from a compatible version) */ if (d.record.extraLength == sizeof(AlarmSoundInfoType)) MemMove(&d.record_sound, ptr + highDataOffset, d.record.extraLength); /* Unlock record */ MemHandleUnlock(t); }
/*********************************************************************** * * 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 {
/* ** Handles events for my custom thumbnail gadgets. */ static Boolean ThumbnailGadgetEvent(FormGadgetTypeInCallback* gadgetP, UInt16 cmd, void* paramP) { Boolean handled = false; DynamicButtonType* btn = (DynamicButtonType*)gadgetP->data; switch (cmd) { case formGadgetDeleteCmd: DynBtnDelete(btn); handled = true; break; case formGadgetDrawCmd: DynBtnDraw(btn); gadgetP->attr.visible = true; handled = true; break; case formGadgetEraseCmd: WinEraseRectangleFrame(btn->frame, &btn->contentRect); break; case formGadgetHandleEventCmd: { EventType* e = (EventType*) paramP; if (e->eType == frmGadgetEnterEvent) { if (DynBtnTrackPen(btn)) { UInt16 attr; /* A thumbnail was selected, display it. */ p.dbI = btn->value; /* Get the category and secret attribute of the current record. */ DmRecordInfo(d.dbR, p.dbI, &attr, NULL, NULL); /* If this is a "private" record, then determine what is to be shown. */ if (attr & dmRecAttrSecret) { switch (d.privateRecordStatus) { case showPrivateRecords: case maskPrivateRecords: FrmGotoForm(p.flags & PFLAGS_WITH_TITLEBAR ? DiddleTForm : DiddleForm); break; /* This case should never be executed!!!!!!! */ case hidePrivateRecords: default: break; } } else { FrmGotoForm(p.flags & PFLAGS_WITH_TITLEBAR ? DiddleTForm : DiddleForm); } DynBtnDraw(btn); } } handled = true; } break; } return handled; }
/*********************************************************************** * * 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); }
/************************************************************ * * FUNCTION: ApptChangeRecord * * DESCRIPTION: Change a record in the Appointment Database * * PARAMETERS: database pointer * database index * database record * changed fields * * RETURNS: ##0 if successful, errorcode if not * * CREATED: 1/25/95 * * BY: Roger Flores * * COMMENTS: Records are not stored with extra padding - they * are always resized to their exact storage space. This avoids * a database compression issue. The code works as follows: * * 1) get the size of the new record * 2) make the new record * 3) pack the packed record plus the changes into the new record * 4) if the sort position is changes move to the new position * 5) attach in position * *************************************************************/ Err ApptChangeRecord(DmOpenRef dbP, UInt16 *index, ApptDBRecordPtr r, ApptDBRecordFlags changedFields) { Err result; Int16 newIndex; UInt16 attributes; Boolean dontMove; MemHandle oldH; MemHandle srcH; MemHandle dstH; ApptDBRecordType src; ApptPackedDBRecordPtr dst = 0; ApptPackedDBRecordPtr cmp; // We do not assume that r is completely valid so we get a valid // ApptDBRecordPtr... if ((result = ApptGetRecord(dbP, *index, &src, &srcH)) != 0) return result; // and we apply the changes to it. if (changedFields.when) src.when = r->when; if (changedFields.alarm) src.alarm = r->alarm; if (changedFields.repeat) src.repeat = r->repeat; if (changedFields.exceptions) src.exceptions = r->exceptions; if (changedFields.description) src.description = r->description; if (changedFields.note) src.note = r->note; // Allocate a new chunk with the correct size and pack the data from // the unpacked record into it. dstH = DmNewHandle(dbP, (UInt32) ApptPackedSize(&src)); if (dstH) { dst = MemHandleLock (dstH); ApptPack (&src, dst); } MemHandleUnlock (srcH); if (dstH == NULL) return dmErrMemError; // If the sort position is changed move to the new position. // Check if any of the key fields have changed. if ((!changedFields.when) && (! changedFields.repeat)) goto attachRecord; // repeating events aren't in sorted order // Make sure *index-1 < *index < *index+1, if so it's in sorted // order. Leave it there. if (*index > 0) { // This record wasn't deleted and deleted records are at the end of the // database so the prior record may not be deleted! cmp = MemHandleLock (DmQueryRecord(dbP, *index-1)); dontMove = (ApptComparePackedRecords (cmp, dst, 0, NULL, NULL, 0) <= 0); MemPtrUnlock (cmp); } else dontMove = true; if (dontMove && (*index+1 < DmNumRecords (dbP))) { DmRecordInfo(dbP, *index+1, &attributes, NULL, NULL); if ( ! (attributes & dmRecAttrDelete) ) { cmp = MemHandleLock (DmQueryRecord(dbP, *index+1)); dontMove &= (ApptComparePackedRecords (dst, cmp, 0, NULL, NULL, 0) <= 0); MemPtrUnlock (cmp); } } if (dontMove) goto attachRecord; // The record isn't in the right position. Move it. newIndex = ApptFindSortPosition (dbP, dst); DmMoveRecord (dbP, *index, newIndex); if (newIndex > *index) newIndex--; *index = newIndex; // return new position attachRecord: // Attach the new record to the old index, the preserves the // category and record id. result = DmAttachRecord (dbP, index, dstH, &oldH); MemPtrUnlock(dst); if (result) return result; MemHandleFree(oldH); return 0; }
static Boolean ExamDetailsFormSave(void) { MemHandle newExam=NULL; UInt16 index = dmMaxRecordIndex; ListType *course; ControlType *course_tr, *date_tr, *time_tr; Char *room; Char empty[1]={'\0'}; FieldType *fldRoom; course = GetObjectPtr(LIST_exd_course); course_tr = GetObjectPtr(LIST_exd_course_trigger); date_tr = GetObjectPtr(SELECTOR_exd_date); time_tr = GetObjectPtr(SELECTOR_exd_time); fldRoom = GetObjectPtr(FIELD_exd_room); room = FldGetTextPtr(fldRoom); if (room == NULL) room=empty; if (gExamsLastSelRowUID == 0) { // New record newExam = DmNewRecord(DatabaseGetRefN(DB_MAIN), &index, sizeof(ExamDBRecord)); } else { // Load record DmFindRecordByID(DatabaseGetRefN(DB_MAIN), gExamsLastSelRowUID, &index); newExam = DmGetRecord(DatabaseGetRefN(DB_MAIN), index); } if (! newExam) { // Could not create entry FrmAlert(ALERT_nomem); return false; } else { UInt16 attr=0; ExamDBRecord ex, *ep; ep = (ExamDBRecord *)MemHandleLock(newExam); ex.type=TYPE_EXAM; ex.course=gExamDetailsItemIDs[LstGetSelection(course)]; ex.note = (gExamsLastSelRowUID == 0) ? 0 : ep->note; ex.date.year = gExamDetailsDate.year; ex.date.month = gExamDetailsDate.month; ex.date.day = gExamDetailsDate.day; ex.begin.hours = gExamDetailsBegin.hours; ex.begin.minutes = gExamDetailsBegin.minutes; ex.end.hours = gExamDetailsEnd.hours; ex.end.minutes = gExamDetailsEnd.minutes; ex.flags = 0x0000; StrNCopy(ex.room, room, sizeof(ex.room)); DmWrite(ep, 0, &ex, sizeof(ExamDBRecord)); MemHandleUnlock(newExam); DmReleaseRecord(DatabaseGetRef(), index, false); DmRecordInfo(DatabaseGetRef(), index, &attr, NULL, NULL); attr |= DatabaseGetCat(); DmSetRecordInfo(DatabaseGetRef(), index, &attr, NULL); DatabaseSort(); } AlarmReset(DatabaseGetRef()); return true; }
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)); } }
/* ** FinishXferMode */ void FinishXferMode(void) { KleenexType kleenex; DtbkRepeatInfoType repeat; FormType* frm = FrmGetActiveForm(); SysDBListItemType* pluglistP = NULL; Int16 current_plug = -1; UInt32 result; Boolean is_goto = false; Err err = errNone; Char cat_name[dmCategoryLength]; Char* note = NULL; UInt16 attr; /* Zero the kleenex */ MemSet(&kleenex, sizeof(KleenexType), 0); /* Bail if no plugins installed */ if (!d.xfer.pluglistH) { FrmAlert(NoPluginInstalled); return; } /* Lock the plugin list */ pluglistP = MemHandleLock(d.xfer.pluglistH); current_plug = GetCurrentXferAppListIndex(); if (current_plug == -1) { FrmAlert(NoPluginSelected); MemHandleUnlock(d.xfer.pluglistH); return; } /* Set the version */ if (pluglistP[current_plug].version & IBVERSION_PICTURE) kleenex.version = IBVERSION_PICTURE; else if (pluglistP[current_plug].version & IBVERSION_ORIG) kleenex.version = IBVERSION_ORIG; else abort(); /* Add flag notifier */ kleenex.version |= IBVERSION_FLAGS; /* Set flags */ if (d.hires) kleenex.flags = IBFLAG_HIRES; /* Set the current record index */ kleenex.sketchRecordNum = p.dbI; /* Set the pick text */ kleenex.text = GetLink(FldGetTextPtr(GetObjectPointer(frm, XferField))); if (!kleenex.text) { FlashWaitMessage(XferNoTextString); MemHandleUnlock(d.xfer.pluglistH); return; } /* Set the title text */ kleenex.title = MemHandleLock(d.record_name); /* Set the category text */ DmRecordInfo(d.dbR, p.dbI, &attr, NULL, NULL); CategoryGetName(d.dbR, attr & dmRecAttrCategoryMask, cat_name); kleenex.category = cat_name; /* Set the note */ note = MemHandleLock(d.record_note); if (StrLen(note)) kleenex.note = note; /* Set the seconds for the alarm */ if (recordIsAlarmSet) kleenex.alarm_secs = d.record.alarmSecs; /* Set the repeat information */ kleenex.repeat = &repeat; switch (d.record.repeatInfo.repeatType) { case repeatDaily: case repeatWeekly: case repeatMonthlyByDay: case repeatMonthlyByDate: case repeatYearly: repeat.repeatType = d.record.repeatInfo.repeatType - 1; /* fix offset caused by repeatHourly */ repeat.repeatFrequency = d.record.repeatInfo.repeatFrequency; repeat.repeatEndDate = d.record.repeatInfo.repeatEndDate; repeat.repeatOn = d.record.repeatInfo.repeatOn; repeat.repeatStartOfWeek = d.record.repeatInfo.repeatStartOfWeek; break; case repeatNone: case repeatHourly: default: kleenex.repeat = NULL; } /* Set the priority */ kleenex.priority = d.record.priority + 1; /* DiddleBug priority is zero-based */ /* Set the completion flag */ if ((d.xfer.complete || (xferCompleteIsAlways)) && !(xferCompleteIsNever)) kleenex.is_complete = 1; else kleenex.is_complete = 0; /* Load the sketch data */ if (kleenex.version & IBVERSION_PICTURE) { if (!d.sonyClie || !d.hires) { kleenex.data = BmpGetBits(WinGetBitmap(d.winbufM)); kleenex.data_size = BmpBitsSize(WinGetBitmap(d.winbufM)); } else { kleenex.data = BmpGetBits(WinGetBitmap(d.winbufM)); kleenex.data_size = HRBmpBitsSize(d.sonyHRRefNum, WinGetBitmap(d.winbufM)); } } /* Call the plugin */ err = SysAppLaunch(pluglistP[current_plug].cardNo, pluglistP[current_plug].dbID, 0, boogerPlugLaunchCmdBlowNose, (MemPtr)&kleenex, &result); /* Clean up some stuff */ MemHandleUnlock(d.xfer.pluglistH); MemPtrFree(kleenex.text); if (err || result) { FrmAlert(PluginError); return; } /* Just to save some typing */ is_goto = (((p.flags&PFLAGS_XFER_GOTO) || (xferGotoIsAlways)) && !(xferGotoIsNever)); if (!is_goto) FlashWaitMessage(XferSavingString); /* Clean up some more */ MemHandleUnlock(d.record_name); MemHandleUnlock(d.record_note); /* Delete the sketch if selected */ if (p.flags&PFLAGS_XFER_DELETE) DoCmdRemove(); /* Goto the new sketch if required */ if (is_goto) { /* Clean up */ MemHandleFree(d.xfer.pluglistH); d.xfer.pluglistH = NULL; /* Switch to other application */ err = SysUIAppSwitch(kleenex.booger.cardNo, kleenex.booger.dbID, kleenex.booger.cmd, kleenex.booger.cmdPBP); /* Clean up on error */ if (err && kleenex.booger.cmdPBP) MemPtrFree(kleenex.booger.cmdPBP); } else { if (kleenex.booger.cmdPBP) MemPtrFree(kleenex.booger.cmdPBP); } CancelXferMode(); }
UInt32 ApptAlarmMunger ( DmOpenRef inDbR, UInt32 inAlarmStart, UInt32 inAlarmStop, PendingAlarmQueueType * inAlarmInternalsP, UInt16* ioCountP, DatebookAlarmType * outAlarmListP, Boolean* outAudibleP ) { UInt16 alarmListSize; UInt16 baseIndex = 0; UInt16 numRecords; UInt16 numAlarms = 0; UInt16 recordNum; MemHandle recordH; ApptDBRecordType apptRec; ApptPackedDBRecordPtr r; UInt32 alarmTime; UInt32 earliestAlarm = 0; UInt32 uniqueID; Boolean skip; UInt16 i; UInt16 index; UInt16 dismissedCount = 0; UInt32 * dismissedListP = 0; if ( outAudibleP ) { *outAudibleP = false; } if ( ioCountP ) { alarmListSize = *ioCountP; } else { alarmListSize = 0; } if (inAlarmInternalsP) { dismissedCount = GetDismissedAlarmCount (inAlarmInternalsP); dismissedListP = GetDismissedAlarmList (inAlarmInternalsP); } numRecords = DmNumRecords (inDbR); for (recordNum = 0; recordNum < numRecords; recordNum++) { recordH = DmQueryRecord (inDbR, recordNum); DmRecordInfo (inDbR, recordNum, NULL, &uniqueID, NULL); if ( !recordH ) { break; } r = (ApptPackedDBRecordPtr) MemHandleLock (recordH); if ( r->flags.alarm ) { ApptUnpack (r, &apptRec); // Get the first alarm on or after inAlarmStart alarmTime = ApptGetAlarmTime (&apptRec, inAlarmStart); // If in range, add the alarm to the output if ( alarmTime && (alarmTime >= inAlarmStart) && (alarmTime <= inAlarmStop) ) { skip = false; index = numAlarms; if (inAlarmInternalsP) { // If this alarm was snoozed, make room for it at the front of the list if (uniqueID == inAlarmInternalsP->snoozeAnchorUniqueID) { // If the list is already full, don't bother shifting its contents. // The snoozed alarm will overwrite the oldest alarm, which is at // the front of the list. // If the list is empty, there's nothing to shift. if (outAlarmListP && (index != 0) && (index != alarmListSize)) { MemMove (&outAlarmListP[1], &outAlarmListP[0], (alarmListSize - 1) * sizeof(*outAlarmListP) ); } // The snoozed alarm is placed at the front of the list index = 0; // Protect the snoozed alarm from being pushed out of a full list baseIndex = 1; } // Otherwise, skip over any alarms that have already been dismissed else if (dismissedCount && (alarmTime == inAlarmStart)) { for (i = 0; i < dismissedCount; i++) { if (dismissedListP [i] == uniqueID) { skip = true; break; } } } } if (!skip) { // If collecting alarms, add it to the list if (outAlarmListP) { // If the alarm list is too large, push the oldest alarm off of the // queue to make room for the new one if (index >= alarmListSize) { // baseIndex is usually 0, but will be set to 1 while snoozing to // keep the snoozed alarm from being pushed out of the queue MemMove (&outAlarmListP[baseIndex], &outAlarmListP[baseIndex + 1], (alarmListSize - baseIndex - 1) * sizeof(*outAlarmListP) ); index = alarmListSize - 1; } outAlarmListP[index].recordNum = recordNum; outAlarmListP[index].alarmTime = alarmTime; } // If the event is timed, inform the caller to play the alarm sound if (outAudibleP && (TimeToInt (apptRec.when->startTime) != apptNoTime) ) { *outAudibleP = true; } // Remember the earliest in-range alarm for our return value if ( (alarmTime < earliestAlarm) || (earliestAlarm == 0) ) { earliestAlarm = alarmTime; } numAlarms++; } // don't skip this alarm } // add alarm to output } // an alarm exists MemHandleUnlock (recordH); } if (ioCountP) { *ioCountP = numAlarms; } return earliestAlarm; }
/***************************************************************************** * Function: GadgetDrawHintCurrent * * Description: Draw hint for current gTimeIndex if needed (may be forced NOT * to draw with GadgetSetNeedsRedraw(false)); *****************************************************************************/ void GadgetDrawHintCurrent(void) { Char *tmp, *bot, begin[timeStringLength], end[timeStringLength], *day; MemHandle mc, mt, mh, type; CourseDBRecord c; TimeDBRecord *tc; RectangleType rect, bounds; UInt16 gadgetIndex = FrmGetObjectIndex(gForm, gGadgetID); RGBColorType color, prevColor; UInt16 attr; // Need to check that due to damn f*** DmRecordInfo which will show a // fatal alert when called on non-existing record (this happens for example // right after creating the new database... if ((gTimeIndex >= DmNumRecords(DatabaseGetRef())) || (gCourseIndex >= DmNumRecords(DatabaseGetRef())) ) return; if (gHintDrawn) { // Delete border around previous entry if ( (gTimeDrawnIndex < DmNumRecords(DatabaseGetRef())) && (DmRecordInfo(DatabaseGetRef(), gTimeDrawnIndex, &attr, NULL, NULL) == errNone) ) { attr &= dmRecAttrCategoryMask; if (attr == DatabaseGetCat()) { mt = DmQueryRecord(DatabaseGetRef(), gTimeDrawnIndex); if (mt) { // mt may be null, for example if next is drawn after delete! tc = (TimeDBRecord *)MemHandleLock(mt); if ((tc->type == TYPE_TIME) && GadgetEventIsVisible(tc) ) { TNlist *tmpl = gGadgetTimeList; GadgetTimeListType *gtl = NULL; while (tmpl != NULL) { gtl = tmpl->data; if (gtl->index == gTimeDrawnIndex) { break; } tmpl = tmpl->next; } color.r=tc->color[0]; color.g=tc->color[1]; color.b=tc->color[2]; if (gPrefs.showTimeline) GadgetDrawTimeline(gtErase); if (gtl != NULL) { GadgetDrawTime(tc->begin, tc->end, tc->day, &color, tc->course, gtl->num, gtl->pos); } if (gPrefs.showTimeline) GadgetDrawTimeline(gtDraw); } MemHandleUnlock(mt); } } } } gTimeDrawnIndex=gTimeIndex; gHintDrawn=true; if (DmRecordInfo(DatabaseGetRef(), gCourseIndex, &attr, NULL, NULL) == errNone) { attr &= dmRecAttrCategoryMask; if (attr == DatabaseGetCat()) { // Record is in currently displayed category mc = DmQueryRecord(DatabaseGetRef(), gCourseIndex); if (! mc) return; mt = DmQueryRecord(DatabaseGetRef(), gTimeIndex); if (! mt) return; UnpackCourse(&c, MemHandleLock(mc)); tc = (TimeDBRecord *)MemHandleLock(mt); if ( GadgetEventIsVisible(tc) ) { TNlist *tmpl = gGadgetTimeList; GadgetTimeListType *gtl = NULL; while (tmpl != NULL) { gtl = tmpl->data; if (gtl->index == gTimeDrawnIndex) { break; } tmpl = tmpl->next; } mh = DmGetResource(strRsc, GADGET_STRINGS_WDAYSTART+tc->day); day = (Char *)MemHandleLock(mh); // Lecture Name (Teacher) [Typ] tmp=(Char *)MemPtrNew(StrLen(c.name)+StrLen(c.teacherName)+4+3+CTYPE_SHORT_MAXLENGTH); MemSet(tmp, MemPtrSize(tmp), 0); type = MemHandleNew(1); CourseTypeGetShort(&type, c.ctype); StrPrintF(tmp, "%s (%s) [%s]", c.name, c.teacherName, (Char *)MemHandleLock(type)); MemHandleUnlock(type); MemHandleFree(type); // Fr 08:00 - 09:30 (Room) <-- Example // 3 5 3 5 3+StrLen(room) <-- Num Chars for MemPtrNew bot=(Char *)MemPtrNew(20+sizeof(tc->room)+MemPtrSize(day)); MemSet(bot, MemPtrSize(bot), 0); TimeToAscii(tc->begin.hours, tc->begin.minutes, GadgetGetTimeFormat(), begin); TimeToAscii(tc->end.hours, tc->end.minutes, GadgetGetTimeFormat(), end); mh = DmGetResource(strRsc, GADGET_STRINGS_WDAYSTART+tc->day); StrPrintF(bot, "%s %s - %s (%s)", day, begin, end, tc->room); FrmGetObjectBounds(gForm, gadgetIndex, &bounds); if (gtl != NULL) { GadgetTimeSetRect(&rect, tc->begin, tc->end, tc->day, gtl->num, gtl->pos); RctSetRectangle(&rect, // + inset (two boxes, one black, one white) rect.topLeft.x + 2, rect.topLeft.y + 2, // width - 2 * inset rect.extent.x - 4, // height - 2 * inset rect.extent.y - 4 ); /* Invert color, looks not so nice aka bad color.r=255- tc->color[0]; color.g=255- tc->color[1]; color.b=255- tc->color[2]; */ color.r=255; color.g=255; color.b=255; TNSetForeColorRGB(&color, &prevColor); WinDrawRectangleFrame(simpleFrame, &rect); color.r=0; color.g=0; color.b=0; RctSetRectangle(&rect, rect.topLeft.x-1, rect.topLeft.y-1, rect.extent.x+2, rect.extent.y+2); TNSetForeColorRGB(&color, NULL); WinDrawRectangleFrame(simpleFrame, &rect); TNSetForeColorRGB(&prevColor, NULL); } // WinInvertRectangleFrame(simpleFrame, &rect); GadgetDrawHint(tmp, bot, tc->note); MemPtrFree((MemPtr) tmp); MemPtrFree((MemPtr) bot); MemHandleUnlock(mh); } else { MemHandleUnlock(mc); MemHandleUnlock(mt); GadgetDrawHintNext(); return; } MemHandleUnlock(mc); MemHandleUnlock(mt); } // End attr == current category } }
Int16 AnalizeOneRecord(UInt16 addrattr, Char* src, HappyDays* hd, Boolean *ignore) { Char *p, *q; UInt16 index; Int16 err; Int16 year, month, day; Int16 nth[20]; Int16 count = 0; while (*src == ' ' || *src == '\t') src++; // skip white space // ignore record with exclamation mark if (*src == '!') { if (gPrefsR.ignoreexclamation) return 0; else src++; } if ((q = StrChr(src, '['))) { // [ 이 있는 경우 duration으로 판단 p = q; q = StrChr(src, ']'); if (q) *q = 0; else return 0; do { p++; nth[count++] = StrAToI(p); if (count >= 20) break; } while ((p = StrChr(p, ','))); } if (*src == '*') { // this is multiple event hd->flag.bits.multiple_event = true; if ((p = StrChr(src, ' '))) *p = 0; else goto ErrHandler; if ( *(src+1) != 0 ) { // if src have 'custom' tag hd->custom = src+1; UnderscoreToSpace(src+1); } else hd->custom = 0; src = p+1; while (*src == ' ' || *src == '\t') src++; // skip white space if ((p = StrChr(src, ' '))) *p = 0; else goto ErrHandler; if (*src == '.') { hd->name1 = src+1; hd->name2 = 0; } else { hd->name2 = src; } UnderscoreToSpace(src); src = p+1; while (*src == ' ' || *src == '\t') src++; // skip white space } if (!AnalysisHappyDays(src, &hd->flag, &year, &month, &day)) goto ErrHandler; // convert into date format // if (hd->flag.bits.year) { if ((year < 1904) || (year > 2031) ) goto ErrHandler; else hd->date.year = year - 1904; } else hd->date.year = 0; hd->date.month = month; hd->date.day = day; // 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); } if (count > 0) { Int16 i; HappyDays hdr; for (i = 0; i < count; i++) { MemMove(&hdr, hd, sizeof(hdr)); hdr.flag.bits.nthdays = 1; hdr.nth = nth[i]; if (!hdr.flag.bits.year) goto ErrHandler; err = HDNewRecord(MainDB, &hdr, &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); } } } return 0; ErrHandler: if (*ignore) return 0; switch (FrmCustomAlert(InvalidFormat, ((!hd->name2) ? ((!hd->name1) ? " " : hd->name1) : hd->name2), " ", " ")) { case 0: // EDIT if (!GotoAddress(hd->addrRecordNum)) return -1; case 2: // Ignore all *ignore = true; case 1: break; // Ignore } return 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; }