📄 dateday.c
字号:
/******************************************************************************
*
* Copyright (c) 1995-2003 PalmSource, Inc. All rights reserved.
*
* File: DateDay.c
*
* Release: Palm OS 5 SDK (68K) R3.
*
* Description:
* This is the Datebook application's main module. This module
* starts the application, dispatches events, and stops
* the application.
*
*****************************************************************************/
#include <PalmOS.h>
#include <Graffiti.h>
#include <SelTime.h>
#include <SysEvtMgr.h>
#include <TxtGlue.h> // For TxtGlueUpperChar
#include <PalmUtils.h>
#include "DateAlarm.h"
#include "DateLunar.h" // For DateSupportsLunarCalendar, etc.
#include "Datebook.h"
extern ECApptDBValidate (DmOpenRef dbP);
/***********************************************************************
*
* Global variables, declarded in DateGlobals.c. Because of a bug in
* the Metrowerks compiler, we must compile the globals separately with
* PC-relative strings turned off.
*
***********************************************************************/
extern MemHandle ApptsH;
extern UInt16 NumAppts;
extern MemHandle ApptsOnlyH;
extern UInt16 NumApptsOnly;
extern UInt16 TopVisibleAppt;
extern privateRecordViewEnum CurrentRecordVisualStatus; // applies to current record
extern privateRecordViewEnum PrivateRecordVisualStatus; // applies to all other records
extern UInt16 PendingUpdate; // code of pending day view update
// The following global variables are used to keep track of the edit
// state of the application.
extern UInt16 CurrentRecord; // record being edited
extern Boolean ItemSelected; // true if a day view item is selected
extern UInt16 DayEditPosition; // position of the insertion point in the desc field
extern UInt16 DayEditSelectionLength; // length of the current selection.
extern Boolean RecordDirty; // true if a record has been modified
// The following global variables are only valid while editng the detail
// of an appointment.
extern void* DetailsP;
extern DateType RepeatEndDate;
extern RepeatType RepeatingEventType;
extern UInt16 RepeatStartOfWeek; // status of Repeat Dialog.
// This global variable is only valid while editing the repeat info of an appointment.
extern void * RepeatDetailsP;
extern UInt16 TimeBarColumns; // Number of columns of time bars.
// The following structure is used by the details dialog to hold
// changes made to an appointment record.
typedef struct {
Boolean secret;
UInt8 reserved;
ApptDateTimeType when;
AlarmInfoType alarm;
RepeatInfoType repeat;
} DetailsType;
typedef DetailsType * DetailsPtr;
typedef enum {
dateRangeNone,
dateRangeCurrent,
dateRangeCurrentAndFuture,
dateRangeAll
} DateRangeType;
/***********************************************************************
*
* Internal Functions
*
***********************************************************************/
static void DayViewLoadTable (void);
static void DayViewLayoutDay (Boolean retieve);
static void DayViewDrawTimeBars (void);
static void DayViewInitRow (TablePtr table, UInt16 row, UInt16 apptIndex,
Int16 rowHeight, UInt32 uniqueID, UInt16 iconsWidth, FontID fontID);
static void DayViewUpdateDisplay (UInt16 updateCode);
static Err SplitRepeatingEvent (UInt16* indexP);
#ifdef FORM_GADGET_TYPE_IN_CALLBACK_DEFINED // Added for Compatibility with SDK 4.0 update 1
static Boolean RepeatDescRectHandler(FormGadgetTypeInCallback *gadgetP, UInt16 cmd, void *paramP);
#else
static Boolean RepeatDescRectHandler(FormGadgetType *gadgetP, UInt16 cmd, void *paramP);
#endif
/***********************************************************************
*
* FUNCTION: DoSecurity
*
* DESCRIPTION: Bring up security dialog and then reopen database if
* necessary.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* jaq 6/12/99 Initial Revision
*
***********************************************************************/
void DoSecurity (void)
{
Boolean wasHiding;
UInt16 mode;
wasHiding = (PrivateRecordVisualStatus == hidePrivateRecords);
PrivateRecordVisualStatus = CurrentRecordVisualStatus = SecSelectViewStatus();
if (wasHiding ^ (PrivateRecordVisualStatus == hidePrivateRecords)) //xor on two logical values - mode to open DB has changed
{
// Close the application's data file.
DmCloseDatabase (ApptDB);
mode = (PrivateRecordVisualStatus == hidePrivateRecords) ?
dmModeReadWrite : (dmModeReadWrite | dmModeShowSecret);
ApptDB = DmOpenDatabaseByTypeCreator(datebookDBType, sysFileCDatebook, mode);
ErrFatalDisplayIf(!ApptDB,"Can't reopen DB");
}
//For safety, simply reset the currentRecord
//CurrentRecord = noRecordSelected;
}
/***********************************************************************
*
* FUNCTION: SetDateToNextOccurrence
*
* DESCRIPTION: This routine set the "current date" global variable to
* the date that the specified record occurs on. If the
* record is a repeating appointmnet, we set the date to
* the next occurrence of the appointment. If we are beyond
* the end date of the repeating appointment, we set the
* date to the last occurrence of the event.
*
* PARAMETERS: recordNum - index of appointment record
*
* RETURNED: true if successful, false if not. It's posible that
* a repeating event may have no displayable occurrences.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 8/24/95 Initial Revision
*
***********************************************************************/
static Boolean SetDateToNextOccurrence (UInt16 recordNum)
{
Boolean dateSet = true;
MemHandle recordH;
DateType today;
DateTimeType dateTime;
ApptDBRecordType apptRec;
ApptGetRecord (ApptDB, recordNum, &apptRec, &recordH);
if (! apptRec.repeat)
Date = apptRec.when->date;
// If the appointment is a repeating event, go to the date of the
// next occurrence of the appointment.
else
{
// Get today's date.
TimSecondsToDateTime (TimGetSeconds (), &dateTime);
today.year = dateTime.year - firstYear;
today.month = dateTime.month;
today.day = dateTime.day;
Date = today;
if ( ! ApptNextRepeat (&apptRec, &Date, true))
{
// If we are beyond the end date of the repeating event, display
// the last occurrence of the event.
Date = apptRec.repeat->repeatEndDate;
if ( ! ApptNextRepeat (&apptRec, &Date, false))
{
// It posible that there are no occurences that are displayable
// (ex: an expections is created for each occurrences), if so
// just go to today.
ErrDisplay ("No displayable occurrences of event");
Date = today;
dateSet = false;
}
}
}
MemHandleUnlock (recordH);
return (dateSet);
}
/***********************************************************************
*
* FUNCTION: GetTime
*
* DESCRIPTION: This routine selects the start and end time of an event.
*
* PARAMETERS: startP - passed: current start time
* returned: selected start time
* endtP - passed: current end time
* returned: selected end time
* titleID - resource id of the title to display in the
* time picker dialog.
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 10/24/95 Initial Revision
*
***********************************************************************/
static Boolean GetTime (TimePtr startP, TimePtr endP, UInt16 titleStrID)
{
Char* title;
TimeType start, end;
Boolean selected;
Boolean untimed;
DateTimeType dateTime;
Int16 firstDisplayHour;
// Get today's date, are we displaying today?
TimSecondsToDateTime (TimGetSeconds (), &dateTime);
if ( Date.year == dateTime.year - firstYear &&
Date.month == dateTime.month &&
Date.day == dateTime.day)
{
firstDisplayHour = dateTime.hour+1;
}
else //not today
{
firstDisplayHour = DayStartHour;
}
// If the event is untimed, pass the default start time
// and duration.
if (TimeToInt (*startP) == apptNoTime)
{
untimed = true;
start.hours = min (firstDisplayHour, hoursPerDay-1);
start.minutes = 0;
end.hours = min (firstDisplayHour + 1, hoursPerDay);
end.minutes = 0;
}
else
{
untimed = false;
start = *startP;
end = *endP;
}
title = MemHandleLock(DmGetResource (strRsc, titleStrID));
selected = SelectTime (&start, &end, untimed, title, DayStartHour, DayEndHour,start.hours);
MemPtrUnlock (title);
if (selected)
{
*startP = start;
*endP = end;
}
return (selected);
}
/***********************************************************************
*
* FUNCTION: ShowObject
*
* DESCRIPTION: This routine set an object usable and draws the object if
* the form it is in is visible.
*
* PARAMETERS: frm - pointer to a form
* objectID - id of the object to set usable
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
*
***********************************************************************/
static void ShowObject (FormPtr frm, UInt16 objectID)
{
FrmShowObject (frm, FrmGetObjectIndex (frm, objectID));
}
/***********************************************************************
*
* FUNCTION: HideObject
*
* DESCRIPTION: This routine set an object not-usable and erases it
* if the form it is in is visible.
*
* PARAMETERS: frm - pointer to a form
* objectID - id of the object to set not usable
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 2/21/95 Initial Revision
*
***********************************************************************/
static void HideObject (FormPtr frm, UInt16 objectID)
{
FrmHideObject (frm, FrmGetObjectIndex (frm, objectID));
}
/***********************************************************************
*
* FUNCTION: DeleteRecord
*
* DESCRIPTION: This routine deletes the specified appointment record.
*
* PARAMETERS: record index
*
* RETURNED: true if the record was deleted, false if the delete
* operation was canceled.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 8/1/95 Initial Revision
* kcr 10/24/95 fixed bug with selection index of 'SaveBackup'
* object
* rbb 5/20/99 Added support for deleting "Current & Future"
* gap 8/01/00 add attention manager support
*
***********************************************************************/
static Boolean DeleteRecord (UInt16 recordNum)
{
Err err = errNone;
UInt16 ctlIndex;
UInt16 alertButton = RangeAllButton;
FormPtr alert;
MemHandle recordH;
Boolean archive;
Boolean exception = false;
ApptDBRecordType apptRec;
ApptDBRecordFlags apptFlags = {};
RepeatInfoType repeatInfo;
DateRangeType dateRange = dateRangeAll;
Boolean hasAlarm;
// If we're changing a repeating appointmemt, check if all occurrences
// are being changed, or if an exception is being created.
ApptGetRecord (ApptDB, recordNum, &apptRec, &recordH);
if (apptRec.repeat && ApptHasMultipleOccurences(&apptRec))
{
alert = FrmInitForm (RangeDialog);
alertButton = FrmDoDialog (alert);
FrmDeleteForm (alert);
// If the alert was canceled don't delete the record.
if (alertButton == RangeCancelButton)
{
dateRange = dateRangeNone;
}
else if (alertButton == RangeCurrentButton)
{
dateRange = dateRangeCurrent;
exception = true;
}
else if (alertButton == RangeFutureButton)
{
// When editing the first instance, deleting "this and future"
// will cause the event to disappear. Modify the dialog result
// to trigger the confirmation dialog.
if (DateToDays(apptRec.when->date) != DateToDays(Date))
{
dateRange = dateRangeCurrentAndFuture;
repeatInfo = *(apptRec.repeat);
}
else
{
dateRange = dateRangeAll;
}
}
}
hasAlarm = (apptRec.alarm != NULL);
// Release the appointment record (apptRec is no longer valid)
MemHandleUnlock (recordH);
switch (dateRange)
{
// ignore dateRangeNone
case dateRangeCurrent:
// if the selected event had an alarm, be sure to remove it
// from the posted alarm queue before the event is changed.
if (hasAlarm)
DeleteAlarmIfPosted(recordNum);
// Add an exception to the current record.
err = ApptAddException (ApptDB, &recordNum, Date);
break;
case dateRangeCurrentAndFuture:
// if the selected event had an alarm, be sure to remove it
// from the posted alarm queue before the event is changed.
if (hasAlarm)
DeleteAlarmIfPosted(recordNum);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -