home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
linuxmafia.com 2016
/
linuxmafia.com.tar
/
linuxmafia.com
/
pub
/
palmos
/
progect-src-0.20.tar.gz
/
progect-src-0.20.tar
/
progect-0.20
/
task.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-10-26
|
73KB
|
2,958 lines
/* -*-Mode:C; tab-width:4; indent-tabs-mode:t; c-file-style:"stroustrup";-*- */
// $Id: task.c,v 1.13 2000/10/22 18:35:27 burgbach Exp $
#include <PalmOS.h>
#include "task.h"
#include "progect.h"
#include "progectdb.h"
#include "progectRsc.h"
#include "ToDoDB.h"
#include "MemoDB.h"
#include "AddressDB.h"
/****************************************************************************
* Name : TaskSetAttr
* Desc : set the attributes of a task
* Parm :
* -> db to search
* -> index of record
* -> new attributes
* Out : pgErr
* Auth : lb, 22.08.2000
***************************************************************************/
pgErr TaskSetAttr(DmOpenRef dbP, UInt16 index, TaskAttrType attr)
{
MemHandle h;
TaskRecordType *p;
h = DmGetRecord(dbP, index);
#ifdef __PG_EXTRA_CHECK__
if (!h)
return pgError;
#endif
p = MemHandleLock(h);
DmWrite(p, OffsetOf(TaskRecordType, attr), &attr, sizeof(UInt16));
MemHandleUnlock(h);
DmReleaseRecord(dbP, index, true);
return pgOK;
} // pgErr TaskSetAttr(DmOpenRef dbP, UInt16 index, TaskAttrType attr)
/****************************************************************************
* Name : TaskGetAttr
* Desc : get the attributes of a task
* Parm :
* -> db to search
* -> index of record
* Out : attributes
* Auth : lb, 22.08.2000
***************************************************************************/
TaskAttrType TaskGetAttr(DmOpenRef dbP, UInt16 index)
{
MemHandle h;
TaskRecordType *p;
TaskAttrType attr;
h = DmQueryRecord(dbP, index);
#ifdef __PG_EXTRA_CHECK__
if (!h)
return 0;
#endif
p = MemHandleLock(h);
attr = p->attr.bits;
MemHandleUnlock(h);
return attr;
} // UInt16 TaskGetAttr(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetFormat
* Desc : set the format of a task
* Parm :
* -> db to search
* -> index of record
* -> new format
* Out : pgErr
* Auth : lb, 22.08.2000
***************************************************************************/
pgErr TaskSetFormat(DmOpenRef dbP, UInt16 index, TaskFormatType format)
{
MemHandle h;
TaskRecordType *p;
h = DmGetRecord(dbP, index);
#ifdef __PG_EXTRA_CHECK__
if (!h)
return pgError;
#endif
p = MemHandleLock(h);
DmWrite(p, OffsetOf(TaskRecordType, format), &format, sizeof(UInt16));
MemHandleUnlock(h);
DmReleaseRecord(dbP, index, true);
return pgOK;
} // pgErr TaskSetFormat(DmOpenRef dbP, UInt16 index, TaskFormatType format)
/****************************************************************************
* Name : TaskGetFormat
* Desc : get the format of a task
* Parm :
* -> db to search
* -> index of record
* Out : format
* Auth : lb, 26.08.2000
***************************************************************************/
TaskFormatType TaskGetFormat(DmOpenRef dbP, UInt16 index)
{
MemHandle h;
TaskRecordType *p;
TaskFormatType format;
h = DmQueryRecord(dbP, index);
#ifdef __PG_EXTRA_CHECK__
if (!h)
return 0;
#endif
p = MemHandleLock(h);
format = p->format.bits;
MemHandleUnlock(h);
return format;
} // TaskFormatType TaskGetFormat(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetLevel
* Desc : set the level of a task
* Parm :
* -> db to search
* -> index of record
* -> new level (0-31)
* Out : pgErr
* Auth : lb, 28.07.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
pgErr TaskSetLevel(DmOpenRef dbP, UInt16 index, UInt8 level)
{
TaskAttrType attr;
if (level > 31)
return pgError;
attr = TaskGetAttr(dbP, index);
attr.level = level;
TaskSetAttr(dbP, index, attr);
return pgOK;
} // pgErr TaskSetLevel(DmOpenRef dbP, UInt16 index, UInt8 level)
/****************************************************************************
* Name : TaskGetLevel
* Desc : get the level of a task
* Parm :
* -> db to search
* -> index of record
* Out : level, 0 if not found
* Auth : lb, 27.07.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
UInt8 TaskGetLevel(DmOpenRef dbP, UInt16 index)
{
return TaskGetAttr(dbP, index).level;
} // UInt8 TaskGetLevel(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetPriority
* Desc : set the priority of a task
* Parm :
* -> db to search
* -> index of record
* -> new priority
* Out :
* Auth : lb, 06.08.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
pgErr TaskSetPriority(DmOpenRef dbP, UInt16 index, UInt8 priority)
{
MemHandle h;
TaskTypePtr p;
h = DmGetRecord(dbP, index);
p = MemHandleLock(h);
DmWrite(p, OffsetOf(TaskType, priority), &priority, sizeof(UInt8));
MemHandleUnlock(h);
DmReleaseRecord(dbP, index, true);
return pgOK;
} // void TaskSetPriority(DmOpenRef dbP, UInt16 index, UInt8 priority)
/****************************************************************************
* Name : TaskGetPriority
* Desc : get the priority of a task
* Parm :
* -> db to search
* -> index of record
* Out : level, 0 if not found
* Auth : lb, 06.08.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
UInt8 TaskGetPriority(DmOpenRef dbP, UInt16 index)
{
MemHandle h;
TaskTypePtr p;
UInt8 priority;
h = DmQueryRecord(dbP, index);
p = MemHandleLock(h);
priority = p->priority;
MemHandleUnlock(h);
return priority;
} // UInt8 TaskGetPriority(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetHasChild
* Desc : set the hasChild field of task
* Parm :
* -> db to search
* -> index of the record
* -> value of hasChild field
* Out :
* Auth : lb, 28.07.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
pgErr TaskSetHasChild(DmOpenRef dbP, UInt16 index, Boolean hasChild)
{
TaskAttrType attr;
attr = TaskGetAttr(dbP, index);
attr.hasChild = hasChild;
TaskSetAttr(dbP, index, attr);
return pgOK;
} // pgErr TaskSetHasChild(DmOpenRef dbP, UInt16 index, Boolean hasChild)
/****************************************************************************
* Name : TaskGetHasChild
* Desc : get the hasChild field of task
* Parm :
* -> db to search
* -> index of the record
* Out : hasChild field value
* Auth : lb, 28.07.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
Boolean TaskGetHasChild(DmOpenRef dbP, UInt16 index)
{
return TaskGetAttr(dbP, index).hasChild;
} // Boolean TaskGetHasChild(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetHasPrev
* Desc : set the firstChild field of task
* Parm :
* -> db to search
* -> index of the record
* -> value of hasPrev field
* Out :
* Auth : lb, 28.07.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
pgErr TaskSetHasPrev(DmOpenRef dbP, UInt16 index, Boolean hasPrev)
{
TaskAttrType attr;
attr = TaskGetAttr(dbP, index);
attr.hasPrev = hasPrev;
TaskSetAttr(dbP, index, attr);
return pgOK;
} // pgErr TaskSetHasPrev(DmOpenRef dbP, UInt16 index, Boolean hasPrev)
/****************************************************************************
* Name : TaskGetHasPrev
* Desc : get the firstChild field of task
* Parm :
* -> db to search
* -> index of the record
* Out : firstChild field value
* Auth : lb, 28.07.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
Boolean TaskGetHasPrev(DmOpenRef dbP, UInt16 index)
{
return TaskGetAttr(dbP, index).hasPrev;
} // Boolean TaskGetHasPrev(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskGetHasNext
* Desc : get the hasNext field of task
* Parm :
* -> db to search
* -> index of the record
* Out : hasNext field value
* Auth : lb, 28.07.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
Boolean TaskGetHasNext(DmOpenRef dbP, UInt16 index)
{
return TaskGetAttr(dbP, index).hasNext;
} // Boolean TaskGetHasNext(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetHasNext
* Desc : set the hasNext field of task
* Parm :
* -> db to search
* -> index of the record
* -> next field
* Out :
* Auth : lb, 28.07.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
pgErr TaskSetHasNext(DmOpenRef dbP, UInt16 index, Boolean next)
{
TaskAttrType attr;
attr = TaskGetAttr(dbP, index);
attr.hasNext = next;
TaskSetAttr(dbP, index, attr);
return pgOK;
} // pgErr TaskSetHasNext(DmOpenRef dbP, UInt16 index, Boolean next)
/****************************************************************************
* Name : TaskIsOpened
* Desc : see if task is opened
* Parm :
* -> db to search
* -> index of the record
* Out :
* Auth : lb, 01.08.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
Boolean TaskIsOpened(DmOpenRef dbP, UInt16 index)
{
return TaskGetAttr(dbP, index).opened;
} // Boolean TaskIsOpened(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskIsVisible
* Desc : true if task is first level, or in an opened hierarchy
* Parm :
* -> db to search
* -> index of the record
* Out :
* Auth : lb, 02.08.2000
* Mod : lb, 24.08.2000
* don't look beyond gRefLevel
***************************************************************************/
Boolean TaskIsVisible(DmOpenRef dbP, UInt16 index)
{
UInt8 comp;
// hide done tasks
if ((((comp = TaskGetCompleted(dbP, index)) == 10) || comp == ACTION_OK) &&
gProjectPrefs.hideDoneTasks)
return false;
while (TaskGetLevel(dbP, index) > gRefLevel + 1)
{
index = TaskGetFatherIndex(dbP, index);
if (!TaskIsOpened(dbP, index))
return false;
}
return true;
} // Boolean TaskIsVisible(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskMakeVisible
* Desc : open all this task's fathers
* Parm :
* -> db to search
* -> index of the record
* Out :
* Auth : lb, 19.10.2000
***************************************************************************/
void TaskMakeVisible(DmOpenRef dbP, UInt16 index)
{
UInt8 comp;
// hide done tasks on => nothing to do, the task is hidden
if ((((comp = TaskGetCompleted(dbP, index)) == 10) || comp == ACTION_OK) &&
gProjectPrefs.hideDoneTasks)
return;
while (TaskGetLevel(dbP, index) > gRefLevel + 1)
{
index = TaskGetFatherIndex(dbP, index);
if (!TaskIsOpened(dbP, index))
TaskSetOpened(dbP, index, true);
}
} // void TaskMakeVisible(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskToggleIsOpened
* Desc : toggle isOpened flag
* Parm :
* -> db to search
* -> index of the record
* Out :
* Auth : lb, 01.08.2000
* Mod : lb, 22.08.2000
* new preferences scheme
***************************************************************************/
pgErr TaskToggleIsOpened(DmOpenRef dbP, UInt16 index)
{
TaskAttrType attr;
attr = TaskGetAttr(dbP, index);
attr.opened = !attr.opened;
TaskSetAttr(dbP, index, attr);
return pgOK;
} // pgErr TaskToggleIsOpened(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetOpened
* Desc : set isOpened flag
* Parm :
* -> db to search
* -> index of the record
* Out :
* Auth : lb, 04.08.2000
* Mod : lb, 22.08.2000
* new preferences scheme
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
pgErr TaskSetOpened(DmOpenRef dbP, UInt16 index, Boolean value)
{
TaskAttrType attr;
attr = TaskGetAttr(dbP, index);
attr.opened = value;
TaskSetAttr(dbP, index, attr);
return pgOK;
} // pgErr TaskSetOpened(DmOpenRef dbP, UInt16 index, Boolean value)
/****************************************************************************
* Name : TaskGetFatherIndex
* Desc : get the father of a task
* Parm :
* -> db to search
* -> index of the record
* Out : father, dmMaxRecordIndex if not found
* Auth : lb, 28.07.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
UInt16 TaskGetFatherIndex(DmOpenRef dbP, UInt16 index)
{
UInt16 prev = 0;
UInt16 sindex;
UInt8 level;
level = TaskGetLevel(dbP, index);
// top level tasks have no father
if (level == FIRST_LEVEL)
return prev;
sindex = index - 1;
while (sindex < index)
{
if (TaskGetLevel(dbP, sindex) == level - 1)
{
prev = sindex;
break;
}
sindex--;
}
return prev;
} // UInt16 TaskGetFatherIndex(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskGetPrevIndex
* Desc : get the previous of a task
* Parm :
* -> db to search
* -> index of the record
* Out : previous, dmMaxRecordIndex if not found
* Auth : lb, 27.07.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
UInt16 TaskGetPrevIndex(DmOpenRef dbP, UInt16 index)
{
UInt16 prev = dmMaxRecordIndex;
UInt16 sindex;
UInt8 level;
UInt8 actLevel;
if (!TaskGetHasPrev(dbP, index))
return prev;
level = TaskGetLevel(dbP, index);
sindex = index - 1;
while (sindex < index)
{
// get level of item sindex
actLevel = TaskGetLevel(dbP, sindex);
// if it's the same, we found
if (actLevel == level)
{
prev = sindex;
break;
}
// if it's less, there's no previous
if (actLevel < level)
{
break;
}
sindex--;
}
return prev;
} // UInt16 TaskGetPrevIndex(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskGetPrevIndexByLevel
* Desc : get the previous of same level from index
* Parm :
* -> db to search
* -> index of the record
* -> level to search for
* Out : previous, dmMaxRecordIndex if not found
* Auth : lb, 31.07.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
UInt16 TaskGetPrevIndexByLevel(DmOpenRef dbP, UInt16 index, UInt8 level)
{
UInt16 prev = dmMaxRecordIndex;
UInt16 sindex = index - 1;
UInt8 actLevel;
// cannot search before first item
if (index == FIRST_INDEX)
return prev;
// search all preceding items
while (sindex < index)
{
// get level of item sindex
actLevel = TaskGetLevel(dbP, sindex);
// if it's the same, we found
if (actLevel == level)
{
prev = sindex;
break;
}
// if it's less, there's no previous
if (actLevel < level)
{
break;
}
sindex--;
}
return prev;
} // UInt16 TaskGetPrevIndexByLevel(DmOpenRef dbP, UInt16 index, UInt8 level)
/****************************************************************************
* Name : TaskGetNextIndex
* Desc : get the next of a task
* Parm :
* -> index of the record
* Out : next, 0 if not found
* Auth : lb, 27.07.2000
* Mod : 01.08.2000
* corrected bug that found a next in other branchs
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
UInt16 TaskGetNextIndex(DmOpenRef dbP, UInt16 index)
{
UInt16 next = 0, lastRecord = DmNumRecords(dbP);
UInt8 level;
UInt8 actLevel;
level = TaskGetLevel(dbP, index);
index++;
while (index < lastRecord)
{
actLevel = TaskGetLevel(dbP, index);
if (actLevel == level)
{
next = index;
break;
}
if (actLevel < level)
{
break;
}
index++;
}
return next;
} // UInt16 TaskGetNextIndex(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskGetNextRelativeIndex
* Desc : get the next of a task, may be the next of a father (TODO be clearer...)
* Parm :
* -> index of the record
* Out : next, 0 if not found
* Auth : lb, 01.08.2000
* Mod : lb, 09.08.2000
* - adding support for subtree viewing
* lb, 28.09.2000
* - return index if index = dmMaxRecordIndex
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
UInt16 TaskGetNextRelativeIndex(DmOpenRef dbP, UInt16 index)
{
UInt16 next = 0, lastRecord = DmNumRecords(dbP);
UInt8 level;
UInt8 actLevel;
if (lastRecord == 0)
return next;
if (index == dmMaxRecordIndex)
return index;
level = TaskGetLevel(dbP, index);
index++;
while (index < lastRecord)
{
actLevel = TaskGetLevel(dbP, index);
//if (actLevel <= level && actLevel >= gRefLevel)
if (actLevel <= level)
{
next = index;
break;
}
index++;
}
return next;
} // UInt16 TaskGetNextRelativeIndex(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetActionState
* Desc : set action state of a task
* Parm :
* -> database pointer
* -> index of the record
* -> action
* Out :
* Auth : lb, 03.08.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
pgErr TaskSetActionState(DmOpenRef dbP, UInt16 index, Boolean action)
{
MemHandle h;
TaskRecordType *p;
UInt8 completed;
h = DmGetRecord(dbP, index);
p = MemHandleLock(h);
completed = p->completed;
// compute a value for completed
if (action)
{
if (completed < ACTION)
{
completed = completed == 10 ? ACTION_OK : ACTION_NO;
}
}
else
{
if (completed > ACTION)
{
completed = completed == ACTION_OK ? 10 : 0;
}
}
DmWrite(p, OffsetOf(TaskRecordType, completed), &completed, sizeof(UInt8));
MemHandleUnlock(h);
DmReleaseRecord(dbP, index, true);
return pgOK;
} // pgErr TaskSetActionState(DmOpenRef dbP, UInt16 index, Boolean action)
/****************************************************************************
* Name : TaskGetCompleted
* Desc : get completed value of a task
* Parm :
* -> database pointer
* -> index of the record
* Out :
* Auth : lb, 04.08.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
UInt8 TaskGetCompleted(DmOpenRef dbP, UInt16 index)
{
MemHandle h;
TaskRecordType *p;
UInt8 value;
h = DmQueryRecord(dbP, index);
p = MemHandleLock(h);
value = p->completed;
MemHandleUnlock(h);
return value;
} // UInt8 TaskGetCompleted(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetCompleted
* Desc : set completed value of a task
* Parm :
* -> database pointer
* -> index of the record
* -> value
* Out :
* Auth : lb, 04.08.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
pgErr TaskSetCompleted(DmOpenRef dbP, UInt16 index, UInt8 value)
{
MemHandle h;
TaskRecordType *p;
h = DmGetRecord(dbP, index);
p = MemHandleLock(h);
DmWrite(p, OffsetOf(TaskRecordType, completed), &value, sizeof(UInt8));
MemHandleUnlock(h);
DmReleaseRecord(dbP, index, true);
return pgOK;
} // pgErr TaskSetCompleted(DmOpenRef dbP, UInt16 index, UInt8 value)
/****************************************************************************
* Name : TaskGetIsDone
* Desc : true if the task is 100% done or ACTION_OK
* Parm :
* -> database pointer
* -> index of the record
* Out : true if the task is 100% done or ACTION_OK
* Auth : lb, 09.08.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
Boolean TaskGetIsDone(DmOpenRef dbP, UInt16 index)
{
MemHandle h;
TaskRecordType *p;
UInt8 value;
h = DmQueryRecord(dbP, index);
p = MemHandleLock(h);
value = p->completed;
MemHandleUnlock(h);
return (value == 10) || (value == ACTION_OK);
} // Boolean TaskGetIsDone(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskGetActionState
* Desc : get action state of a task
* Parm :
* -> database pointer
* -> index of the record
* Out : action status
* Auth : lb, 03.08.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
Boolean TaskGetActionState(DmOpenRef dbP, UInt16 index)
{
MemHandle h;
TaskRecordType *p;
UInt8 completed;
h = DmQueryRecord(dbP, index);
p = MemHandleLock(h);
completed = p->completed;
MemHandleUnlock(h);
return completed > ACTION;
} // Boolean TaskGetActionState(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetDueDate
* Desc : set the due date of a task
* Parm :
* -> database pointer
* -> index of the record
* -> date
* Out :
* Auth : lb, 06.08.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
pgErr TaskSetDueDate(DmOpenRef dbP, UInt16 index, DateType date)
{
MemHandle h;
TaskRecordType *p;
h = DmGetRecord(dbP, index);
if (h)
{
p = MemHandleLock(h);
if (p)
DmWrite(p, OffsetOf(TaskRecordType, dueDate), &date, sizeof(DateType));
MemHandleUnlock(h);
}
DmReleaseRecord(dbP, index, true);
return pgOK;
} // pgErr TaskSetDueDate(DmOpenRef dbP, UInt16 index, DateType date)
/****************************************************************************
* Name : TaskGetDueDate
* Desc : get the due date of a task
* Parm :
* -> database pointer
* -> index of the record
* Out :
* Auth : lb, 03.08.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
DateType TaskGetDueDate(DmOpenRef dbP, UInt16 index)
{
MemHandle h;
TaskRecordType *p;
DateType date;
h = DmQueryRecord(dbP, index);
if (h)
{
p = MemHandleLock(h);
if (p)
date = p->dueDate;
MemHandleUnlock(h);
}
return date;
} // void TaskGetDueDate(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetNote
* Desc : set the note of a task
* Parm :
* -> database pointer
* -> index of the record
* -> pointer to the note (will be copied)
* Out :
* Auth : lb, 22.08.2000
* TODO : better error handling
***************************************************************************/
pgErr TaskSetNote(DmOpenRef dbP, UInt16 index, Char* note)
{
MemHandle h, hNew;
TaskRecordType *p, *pNew;
UInt32 size, uniqueID;
TaskFormatType format;
UInt16 attr, newIndex = DmNumRecords(dbP);
MemPtr extraBlock = NULL;
UInt32 extraSize;
extraSize = TaskGetExtraBlock(dbP, index, NULL);
if (extraSize)
{
extraBlock = MemPtrNew(extraSize);
TaskGetExtraBlock(dbP, index, extraBlock);
}
h = DmQueryRecord(dbP, index);
#ifdef __PG_EXTRA_CHECK__
if (!h)
return pgError;
#endif
p = MemHandleLock(h);
size = TaskRecordTypeSize + StrLen(&p->description) + StrLen(note)
+ extraSize;
hNew = DmNewRecord(dbP, &newIndex, size);
if (!hNew)
{
FrmCustomAlert(AltEmpty,
"No space to store the task. Please free some memory and retry.",
"", "");
return pgError;
}
pNew = MemHandleLock(hNew);
// since we created a record, get the old one more time (he was just
// queried)
MemHandleUnlock(h);
p = MemHandleLock(h);
DmWrite(pNew, 0, p, sizeof(TaskRecordType) - 1);
DmStrCopy(pNew, OffsetOf(TaskRecordType, description), &p->description);
DmStrCopy(pNew,
OffsetOf(TaskRecordType, description) + StrLen(&pNew->description) + 1,
note);
format = p->format.bits;
format.hasNote = *note ? 1 : 0;
DmWrite(pNew, OffsetOf(TaskRecordType, format), &format, sizeof(UInt16));
if (extraSize)
{
DmWrite(pNew,
OffsetOf(TaskRecordType, description) + StrLen(&pNew->description)
+ StrLen(note) + 2,
extraBlock, extraSize);
MemPtrFree(extraBlock);
}
MemHandleUnlock(hNew);
MemHandleUnlock(h);
DmReleaseRecord(dbP, DmNumRecords(dbP) - 1, true);
// to allow sync
// get the unique ID of original task
DmRecordInfo(dbP, index, &attr, &uniqueID, NULL);
// delete original task
DmRemoveRecord(dbP, index);
// move the new task to the good index
DmMoveRecord(dbP, DmNumRecords(dbP) - 1, index);
// set the unique ID of the new task
DmSetRecordInfo(dbP, index, &attr, &uniqueID);
return pgOK;
} // pgErr TaskSetNote(DmOpenRef dbP, UInt16 index, Char* note)
/****************************************************************************
* Name : TaskGetDescription
* Desc : get the description of a task
* Parm :
* -> database pointer
* -> index of the record
* Out : pointer to the desc, use it immediately, it could becomme invalid
* reading only !!!
* Auth : lb, 22.09.2000
* seagull, 9.10.2000
* - allocate tmp buffer (because unlocked ptr make warnning
* under POSE)
* - support direct linked task.
***************************************************************************/
Char* TaskGetDescription(DmOpenRef dbP, UInt16 index)
{
char* desc = NULL;
MemHandle h = NULL;
TaskExtendedRecordType* pTask;
h = DmQueryRecord(dbP, index);
if (h)
{
pTask = MemHandleLock(h);
if (pTask)
{
desc = TaskGetDescriptionByTaskPtr(pTask);
MemHandleUnlock(h);
}
}
return desc;
} // Char* TaskGetDescription(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskGetDescriptionByTaskPtr
* Desc : get the description of a task
* Parm :
* -> Task pointer
* Out : pointer to the desc. must free by caller.
* Auth : seagull, 9.10.2000
***************************************************************************/
Char* TaskGetDescriptionByTaskPtr(TaskExtendedRecordType* pTask)
{
DmOpenRef db = NULL;
MemHandle hLink = NULL;
char* desc = NULL;
char* result = NULL;
if (pTask->format.bits.extendedType)
{
UInt16 index;
UInt16 attr;
AddrDBRecordType item;
if (pTask->format.bits.isMemo)
{
if (! MemoGetDatabase(&db, dmModeReadOnly) &&
! DmFindRecordByID(db, pTask->fields.link.uniqueID, &index) &&
! DmRecordInfo(db, index, &attr, NULL, NULL) &&
! (attr & dmRecAttrDelete) )
{
hLink = DmQueryRecord(db, index);
desc = MemHandleLock(hLink);
}
}
else if (pTask->format.bits.isContact)
{
if (! AddrGetDatabase(&db, dmModeReadWrite) &&
! DmFindRecordByID(db, pTask->fields.link.uniqueID, &index) &&
! DmRecordInfo(db, index, &attr, NULL, NULL) &&
! (attr & dmRecAttrDelete) )
{
AddrGetRecord(db, index, &item, &hLink);
desc = item.fields[name];
}
}
}
else
desc = &pTask->fields.task.description;
if (desc)
{
UInt16 len;
char* pp = desc;
while (*pp && *pp != '\n') pp++;
len = pp - desc;
result = MemPtrNew(len + 1);
MemMove(result, desc, len);
result[len] = '\0';
}
if (db) DmCloseDatabase(db);
if (hLink) MemHandleUnlock(hLink);
return result;
}
/****************************************************************************
* Name : TaskGetNote
* Desc : set the note of a task
* Parm :
* -> database pointer
* -> index of the record
* Out : pointer to the note, use it immediately, it could becomme invalid
* reading only !!!
* Auth : lb, 22.08.2000
* TODO : better error handling
***************************************************************************/
Char* TaskGetNote(DmOpenRef dbP, UInt16 index)
{
MemHandle h;
TaskRecordType *p;
Char* note = NULL;
h = DmQueryRecord(dbP, index);
if (h)
{
p = MemHandleLock(h);
if (!p)
return NULL;
note = &p->description;
// go to the note field
note += StrLen(note) + 1;
if (note > (Char*)p + MemHandleSize(h))
{
MemHandleUnlock(h);
return NULL;
}
MemHandleUnlock(h);
}
return note;
} // Char* TaskGetNote(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetExtraBlockHeadPtr
* Desc : get the given extra block of the given task
* Parm :
* -> the task
* Out :
* Auth : lb, 31.08.2000
* seagull, 10.10.2000
***************************************************************************/
static MemPtr TaskGetExtraBlockHeadPtr(TaskExtendedRecordType* pTask)
{
Char* pExtra;
if (pTask->format.bits.extendedType)
pExtra = &pTask->fields.link.dbName;
else
pExtra = &pTask->fields.task.description +
StrLen(&pTask->fields.task.description) + 1;
pExtra += StrLen(pExtra) + 1;
return (MemPtr)pExtra;
} // static MemPtr TaskGetExtraBlockHeadPtr(TaskExtendedType* pTask)
/****************************************************************************
* Name : TaskSetExtraBlock
* Desc : set the given extra block to the given task
* Parm :
* -> database pointer
* -> index of the record
* -> pointer to the block
* -> size of the block (pass 0 to remove)
* Out :
* Auth : lb, 31.08.2000
* seagull, 10.10.2000
***************************************************************************/
pgErr TaskSetExtraBlock(DmOpenRef dbP, UInt16 index, MemPtr s, UInt32 size)
{
MemHandle h;
TaskExtendedRecordType* p;
UInt16 sizeBase;
// find and lock it's record
h = DmQueryRecord(dbP, index);
#ifdef __PG_EXTRA_CHECK__
if (!h) return pgError;
#endif
p = MemHandleLock(h);
sizeBase = (UInt8*)TaskGetExtraBlockHeadPtr(p) - (UInt8*)p;
//
MemHandleUnlock(h);
h = DmResizeRecord(dbP, index, sizeBase + size);
if (! h)
MessageBox(StrNoMemorySpaces);
else
{
if (size != 0)
{ // write new extra block
h = DmGetRecord(dbP, index);
p = MemHandleLock(h);
DmWrite(p, sizeBase, s, size);
MemHandleUnlock(h);
DmReleaseRecord(dbP, index, true);
}
}
return pgOK;
} // pgErr TaskSetExtraBlock(DmOpenRef dbP, UInt16 index, MemPtr s, UInt32 size)
/****************************************************************************
* Name : TaskGetExtraBlock
* Desc : get the given extra block of the given task
* Parm :
* -> database pointer
* -> index of the record
* -> pointer to the block, pass NULL if you don't want it
* Out : size of the block
* Auth : lb, 31.08.2000
* Rem : gives size = 0 if no extra block
***************************************************************************/
UInt32 TaskGetExtraBlock(DmOpenRef dbP, UInt16 index, MemPtr dest)
{
MemHandle h;
TaskExtendedRecordType* pTask;
MemPtr pExtra;
UInt32 sizeExtra;
h = DmQueryRecord(dbP, index);
pTask = MemHandleLock(h);
pExtra = TaskGetExtraBlockHeadPtr(pTask);
sizeExtra = (UInt8*)pTask + MemPtrSize(pTask) - (UInt8*)pExtra;
if (sizeExtra && dest)
MemMove(dest, pExtra, sizeExtra); // ??? miss alignment ???
MemHandleUnlock(h);
return sizeExtra;
} // UInt32 TaskGetExtraBlock(DmOpenRef dbP, UInt16 index, MemPtr dest)
/****************************************************************************
* Name : TaskGetToDoUniqueID
* Desc : get the uniqueID of the sync ToDo task
* Parm :
* -> database pointer
* -> index of the record
* Out : uniqueID
* Auth : lb, 31.08.2000
***************************************************************************/
UInt32 TaskGetToDoUniqueID(DmOpenRef dbP, UInt16 index)
{
UInt32 uniqueID;
UInt16 size = sizeof(uniqueID);
if (! TaskGetFormat(dbP, index).hasToDo)
return 0;
if (pgOK != TaskGetExtraChunk(dbP, index,
Extra_Link_ToDo, 0xff,
(MemPtr)&uniqueID, &size) )
return 0;
return uniqueID;
} // UInt32 TaskGetToDoUniqueID(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskCopyExtraBlock
* Desc : copy an extra block from a task to another
* Parm :
* -> database pointer
* -> index of the source record
* -> index of the destination record
* Out :
* Auth : lb, 31.08.2000
* Rem :
***************************************************************************/
pgErr TaskCopyExtraBlock(DmOpenRef dbP, UInt16 source, UInt16 dest)
{
MemPtr extraBlock;
UInt32 extraSize;
pgErr status = pgOK;
extraSize = TaskGetExtraBlock(dbP, source, NULL);
if (extraSize)
{
extraBlock = MemPtrNew(extraSize);
if (!extraBlock)
return pgError;
TaskGetExtraBlock(dbP, source, extraBlock);
status = TaskSetExtraBlock(dbP, dest, extraBlock, extraSize);
MemPtrFree(extraBlock);
}
return status;
} // pgErr TaskCopyExtraBlock(DmOpenRef dbP, UInt16 source, UInt16 dest)
/****************************************************************************
* Name : TaskInputDueDate
* Desc : ask user for a due date
* Parm :
* -> database pointer
* -> index of the record
* Out :
* Auth : lb, 03.08.2000
* Rem : bad err handling
* TODO : better error handling
***************************************************************************/
pgErr TaskInputDueDate(DmOpenRef dbP, UInt16 index)
{
TaskRecordType *p;
MemHandle h;
DateType date;
Boolean selected;
UInt16 month, day, year;
date = TaskGetDueDate(dbP, index);
if (date.month == 0)
{
date = gToday;
}
month = date.month;
day = date.day;
year = date.year + YEAR_OFFSET; // year offset
selected = SelectDay(selectDayByDay, &month, &day, &year, "Choose a due date");
if (selected)
{
date.month = month;
date.day = day;
date.year = year - YEAR_OFFSET;
h = DmGetRecord(dbP, index);
p = MemHandleLock(h);
DmWrite(p, OffsetOf(TaskRecordType, dueDate), &date, sizeof(DateType));
MemHandleUnlock(h);
DmReleaseRecord(dbP, index, true);
}
return pgOK;
} // pgErr TaskInputDueDate(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSave
* Desc : save a record (copy it and create as last index)
* In :
* -> record to save
* Out :
* Auth : lb, 03.08.2000
* Rem : doesn't handle err codes
* Mod : lb, 07.09.2000
* - keep the same uniqueID and attr
***************************************************************************/
pgErr TaskSave(UInt16 index)
{
MemHandle hNew, hOld;
TaskRecordType *pNew, *pOld;
UInt32 size = TaskRecordTypeSize, uniqueID;
UInt16 realIndex = dmMaxRecordIndex, attr;
// get a handle on the record to save
hOld = DmQueryRecord(gdbP, index);
// calc the needed size
size = MemHandleSize(hOld);
// get a handle on a newly created record
hNew = DmNewRecord(gdbP, &realIndex, size);
// get a pointer on the record
pNew = MemHandleLock(hNew);
// get a pointer on it
pOld = MemHandleLock(hOld);
// write the data
DmWrite(pNew, 0, pOld, size);
// unlock the pointers
MemHandleUnlock(hNew);
MemHandleUnlock(hOld);
// unlock the record
DmReleaseRecord(gdbP, realIndex, true);
// to allow sync
// get the unique ID of original task
DmRecordInfo(gdbP, index, &attr, &uniqueID, NULL);
// set the unique ID of the new task
DmSetRecordInfo(gdbP, realIndex, &attr, &uniqueID);
return pgOK;
} // pgErr TaskSave(UInt16 index)
/****************************************************************************
* Name : TaskGetSaved
* Desc : get the saved record (copy from last index)
* In :
* -> index to put saved record
* Out :
* Auth : lb, 03.08.2000
* Rem : doesn't handle err codes
* Mod : lb, 07.09.2000
* - keep the same uniqueID and attr
***************************************************************************/
pgErr TaskGetSaved(UInt16 index)
{
MemHandle hNew, hOld;
TaskRecordType *pNew, *pOld;
UInt32 size = TaskRecordTypeSize, uniqueID;
UInt16 attr;
// get a handle on the saved record
hOld = DmQueryRecord(gdbP, DmNumRecords(gdbP) - 1);
// calc the needed size
size = MemHandleSize(hOld);
// get a handle on a newly created record
hNew = DmNewRecord(gdbP, &index, size);
// get a pointer on the record
pNew = MemHandleLock(hNew);
// get a pointer on it
pOld = MemHandleLock(hOld);
// write the data
DmWrite(pNew, 0, pOld, size);
// unlock the pointers
MemHandleUnlock(hNew);
MemHandleUnlock(hOld);
// unlock the record
DmReleaseRecord(gdbP, index, true);
// to allow sync
// get the unique ID of original task
DmRecordInfo(gdbP, DmNumRecords(gdbP)-1, &attr, &uniqueID, NULL);
// set the unique ID of the new task
DmSetRecordInfo(gdbP, index, &attr, &uniqueID);
// remove saved record
DmRemoveRecord(gdbP, DmNumRecords(gdbP) - 1);
// remove replaced record
DmRemoveRecord(gdbP, index + 1);
return pgOK;
} // pgErr TaskGetSaved(UInt16 index)
/****************************************************************************
* Name : TaskRemoveSaved
* Desc : remove the saved record
* In :
* Out :
* Auth : lb, 03.08.2000
* Rem : doesn't handle err codes
***************************************************************************/
pgErr TaskRemoveSaved(void)
{
// remove replaced record
DmRemoveRecord(gdbP, DmNumRecords(gdbP) - 1);
return pgOK;
} // pgErr TaskRemoveSaved(void)
/****************************************************************************
* Name : TaskRemove
* Desc : remove a task and all its children
* In :
* -> index of the task to remove
* Out :
* Auth : lb, 03.08.2000
* Rem : doesn't handle err codes
***************************************************************************/
pgErr TaskRemove(DmOpenRef dbP, UInt16 index)
{
Boolean stillChild = false;
// as long as I have a child, remove it
while (TaskGetHasChild(dbP, index))
{
TaskRemove(dbP, index + 1);
}
if (TaskGetHasNext(dbP, index))
{
if (!TaskGetHasPrev(dbP, index))
{
TaskSetHasPrev(dbP, index + 1, false);
}
stillChild = true;
}
if (TaskGetHasPrev(dbP, index))
{
if (!TaskGetHasNext(dbP, index))
{
TaskSetHasNext(dbP, TaskGetPrevIndex(dbP, index), false);
}
stillChild = true;
}
if (!stillChild)
{
if (TaskGetLevel(dbP, index) != 1)
{
TaskSetHasChild(dbP, TaskGetFatherIndex(dbP, index), false);
}
}
// then, remove me
DmRemoveRecord(dbP, index);
return pgOK;
} // pgErr TaskRemove(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskRemoveDone
* Desc : remove all done tasks
* In :
* Out :
* Auth : lb, 29.08.2000
* Rem : doesn't handle err codes
***************************************************************************/
pgErr TaskRemoveChildren(DmOpenRef dbP, UInt16 index)
{
// as long as I have a child, remove it
while (TaskGetHasChild(dbP, index))
{
TaskRemove(dbP, index + 1);
}
TaskSetHasChild(gdbP, index, false);
return pgOK;
} // pgErr TaskRemoveChildren(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskRemoveDone
* Desc : remove all done tasks
* In :
* Out :
* Auth : lb, 29.08.2000
* Rem : doesn't handle err codes
***************************************************************************/
pgErr TaskRemoveDone(DmOpenRef dbP)
{
UInt16 i = 1, status;
while (i < DmNumRecords(dbP))
{
if (((status = TaskGetCompleted(dbP, i)) == 10) ||
(status == ACTION_OK))
{
TaskRemove(dbP, i);
}
else
{
i++;
}
}
return pgOK;
} // pgErr TaskRemoveDone(DmOpenRef dbP)
/****************************************************************************
* Name : TaskRemoveDoneChildren
* Desc : remove all done tasks in the children of given task
* In :
* Out :
* Auth : lb, 29.08.2000
* Rem : doesn't handle err codes
***************************************************************************/
pgErr TaskRemoveDoneChildren(DmOpenRef dbP, UInt16 index)
{
UInt16 i = index + 1, status, refLevel = TaskGetLevel(dbP, index);
while (i < DmNumRecords(dbP) && TaskGetLevel(dbP, i) > refLevel)
{
if (((status = TaskGetCompleted(dbP, i)) == 10) ||
(status == ACTION_OK))
{
TaskRemove(dbP, i);
}
else
{
i++;
}
}
return pgOK;
} // pgErr TaskRemoveDoneChildren(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskExpandAll
* Desc : set opened flag for all tasks
* In :
* Out :
* Auth : lb, 04.08.2000
* Rem : doesn't handle err codes
***************************************************************************/
pgErr TaskExpand(DmOpenRef dbP, UInt16 index)
{
UInt16 i, num;
UInt8 level;
level = TaskGetLevel(dbP, index);
num = DmNumRecords(dbP);
TaskSetOpened(dbP, index, true);
for (i = index + 1; i < num && TaskGetLevel(dbP, i) > level; i++)
{
TaskSetOpened(dbP, i, true);
}
return pgOK;
} // pgErr TaskExpand(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskCollapseAll
* Desc : unset opened flag for all tasks
* In :
* Out :
* Auth : lb, 04.08.2000
* Rem : doesn't handle err codes
***************************************************************************/
pgErr TaskCollapse(DmOpenRef dbP, UInt16 index)
{
UInt16 i, num;
UInt8 level;
level = TaskGetLevel(dbP, index);
num = DmNumRecords(dbP);
// don't collapse task 0 !!!
if (index != 0)
{
TaskSetOpened(dbP, index, false);
}
for (i = index + 1; i < num && TaskGetLevel(dbP, i) > level; i++)
{
// don't collapse a task without child, or it'll be closed
// when it becomes a child
if (TaskGetHasChild(dbP, i))
{
TaskSetOpened(dbP, i, false);
}
}
return pgOK;
} // pgErr TaskCollapse(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskCalcCompleted
* Desc : calc and set completed by mean of the children
* In :
* -> database pointer
* -> index of father to calc
* Out :
* Auth : lb, 04.08.2000
* Rem : doesn't handle err codes
* warning : this one doesn't recurse down but UP ! You must call is
* on a father whose children are up to date !
***************************************************************************/
pgErr TaskCalcCompleted(DmOpenRef dbP, UInt16 index)
{
UInt16 mean = 0, num = 0, tmp;
UInt16 subtask;
UInt8 level;
if (!TaskGetHasChild(dbP, index))
return pgError;
level = TaskGetLevel(dbP, index);
subtask = index + 1;
while (subtask)
{
tmp = TaskGetCompleted(dbP, subtask);
if (tmp > ACTION)
{
// done = 100%, not done = 0%
tmp = (tmp == ACTION_OK ? 10 : 0);
}
mean += tmp;
num++;
// this one will return 0 if no brother is found
subtask = TaskGetNextIndex(dbP, subtask);
}
TaskSetCompleted(dbP, index, mean / num);
// recurse up, calc for the elders
if (level > 1)
{
TaskCalcCompleted(dbP, TaskGetFatherIndex(dbP, index));
}
return pgOK;
} // pgErr TaskCalcCompleted(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskCalcCompletedAll
* Desc : calc and set completed by mean of the children for all fathers
* In :
* -> database pointer
* Out :
* Auth : lb, 04.08.2000
* Rem : doesn't handle err codes
* warning : this one can be lengthy !!!!
* TODO : optimize it !!!
***************************************************************************/
pgErr TaskCalcCompletedAll(DmOpenRef dbP)
{
UInt16 i;
// children always comes after parents !
for (i = DmNumRecords(dbP) - 1; i > 0; i--)
{
TaskCalcCompleted(dbP, i); // this one controls if i has a child
}
return pgOK;
} // pgErr TaskCalcCompletedAll(DmOpenRef dbP)
/****************************************************************************
* Name : TaskToRight
* Desc : task becomes a child of previous one
* Prm : index of future child
* Out :
* Auth : lb, 27.07.2000
* Mod : lb, 28.07.2000
* new method, work by index
* lb, 24.08.2000
* fixed a bug when moving right the last task
***************************************************************************/
pgErr TaskToRight(DmOpenRef dbP, UInt16 index)
{
UInt16 i;
UInt8 actualLevel;
UInt16 actual;
UInt16 numRec = DmNumRecords(dbP);
// can't push the first one, he must be a first level one
if (index == FIRST_INDEX)
return pgError;
// can't push more than previous level + 1
if (TaskGetLevel(dbP, index - 1) < TaskGetLevel(dbP, index))
return pgError;
// if actual has no next, modify previous
if (!TaskGetHasNext(dbP, index))
{
TaskSetHasNext(dbP, actual = TaskGetPrevIndex(dbP, index), false);
}
// actual loose his next
TaskSetHasNext(dbP, index, false);
// inc level
TaskSetLevel(dbP, index, actualLevel = TaskGetLevel(dbP, index) + 1);
// if a previous exist
if (TaskGetPrevIndex(dbP, index) != dmMaxRecordIndex)
{
// tell him he has a next
TaskSetHasNext(dbP, TaskGetPrevIndex(dbP, index), true);
// actual has a prev
TaskSetHasPrev(dbP, index, true);
}
else
{
// no previous, actual is a first child
// update father
TaskSetHasChild(dbP, TaskGetFatherIndex(dbP, index), true);
// actual has no previous
TaskSetHasPrev(dbP, index, false);
}
// need to update the children
if (TaskGetHasChild(dbP, index))
{
i = index + 1;
// all children go to right without other modification
while (i < numRec && TaskGetLevel(dbP, i) >= actualLevel)
{
TaskSetLevel(dbP, i, TaskGetLevel(dbP, i) + 1);
i++;
}
}
return pgOK;
} // pgErr TaskToRight(UInt16 index)
/****************************************************************************
* Name : TaskToLeft
* Desc : TODO fill
* Prm : index of item to be push to left
* Out :
* Auth : lb, 31.07.2000
* Rem :
* Mod : lb, 09.08.2000
* - update gActualTask for continuous moving
* lb, 24.08.2000
* fixed a bug when moving right the last task
***************************************************************************/
pgErr TaskToLeft(DmOpenRef dbP, UInt16 index)
{
UInt16 i;
UInt8 actualLevel;
UInt16 prev;
UInt16 father;
UInt16 newIndex = index;
Boolean needMove = false;
UInt16 numRec = DmNumRecords(dbP);
// can't push the first one, he must be a first level one
if (index == FIRST_INDEX)
return pgError;
// can't push more than level 1
if (TaskGetLevel(dbP, index) == FIRST_LEVEL)
return pgError;
// to gain some time
father = TaskGetFatherIndex(dbP, index);
// return if I can't find the father or if it's the root
if (!father)
return pgError;
// if previous exists, update its next
if ((prev = TaskGetPrevIndex(dbP, index)) != dmMaxRecordIndex)
{
TaskSetHasNext(dbP, prev, TaskGetHasNext(dbP, index));
}
else
{
// no previous, actual is a first child
// update father
// father still has child if actual has a next
TaskSetHasChild(dbP, father, TaskGetHasNext(dbP, index));
}
// if actual has a next, next takes actual's prev status
if (TaskGetHasNext(dbP, index))
{
TaskSetHasPrev(dbP, TaskGetNextIndex(dbP, index), TaskGetHasPrev(dbP, index));
// actual must be moved outside its parent's scope
// that's before father's next
needMove = true;
}
// if father has no next, modify actual
if (!TaskGetHasNext(dbP, father))
{
TaskSetHasNext(dbP, index, false);
}
else
{
TaskSetHasNext(dbP, index, true);
}
TaskSetHasPrev(dbP, index, true);
if (needMove)
{
newIndex = TaskGetNextRelativeIndex(dbP, father);
if (newIndex == 0)
{
newIndex = DmNumRecords(dbP);
}
DmMoveRecord(dbP, index, newIndex);
// we insert after index, so newIndex becomes newIndex-- after insertion
newIndex--;
gActualTask = newIndex;
}
// dec level
TaskSetLevel(dbP, newIndex, actualLevel = TaskGetLevel(dbP, newIndex) - 1);
// father gain a next
TaskSetHasNext(dbP, father, true);
// need to update the children
if (TaskGetHasChild(dbP, newIndex))
{
newIndex++; // to insert children after actual
i = index + 1;
// if actual has moved, first child is now index
if (needMove)
{
i--;
}
// all children go to left, without other modification
while (i < numRec && TaskGetLevel(dbP, i) >= actualLevel + 2)
{
TaskSetLevel(dbP, i, TaskGetLevel(dbP, i) - 1);
if (needMove)
{
DmMoveRecord(dbP, i, newIndex);
gActualTask--;
}
else
{
i++;
}
}
}
return pgOK;
} // pgErr TaskToLeft(UInt16 index)
/****************************************************************************
* Name : TaskUp
* Desc : push a task up
* Prm :
* -> index of task to push
* Out : Err code
* Auth : lb, 01.08.2000
* Rem :
* Mod : lb, 09.08.2000
* - update gActualTask for continuous moving
***************************************************************************/
pgErr TaskUp(DmOpenRef dbP, UInt16 index)
{
UInt16 prev;
UInt8 level;
UInt16 numRec = DmNumRecords(dbP);
if (!TaskGetHasPrev(dbP, index))
return pgError;
// update flags
prev = TaskGetPrevIndex(dbP, index);
TaskSetHasNext(dbP, prev, TaskGetHasNext(dbP, index));
TaskSetHasPrev(dbP, index, TaskGetHasPrev(dbP, prev));
TaskSetHasPrev(dbP, prev, true);
TaskSetHasNext(dbP, index, true);
// move index
DmMoveRecord(dbP, index, prev);
// update actual task
gActualTask = prev;
// move children
if (TaskGetHasChild(dbP, prev))
{
level = TaskGetLevel(dbP, prev);
// move children behind actual
prev++;
index++;
// while it's a child
while (index < numRec && TaskGetLevel(dbP, index) > level)
{
DmMoveRecord(dbP, index, prev);
prev++;
index++;
}
}
return pgOK;
} // pgErr TaskUp(UInt16 index)
/****************************************************************************
* Name : TaskDown
* Desc : push a task down
* Prm :
* -> index of task to push
* Out : Err code
* Auth : lb, 02.08.2000
* Mod : lb, 09.08.2000
* - update gActualTask for continuous moving
* lb, 17.08.2000
* - fixed crash when moving a task that has children
***************************************************************************/
pgErr TaskDown(DmOpenRef dbP, UInt16 index)
{
UInt16 next;
UInt32 uniqueID;
if (!TaskGetHasNext(dbP, index))
return pgError;
// to locate the task after it has moved
DmRecordInfo(dbP, gActualTask, NULL, &uniqueID, NULL);
next = TaskGetNextIndex(dbP, index);
TaskUp(dbP, next);
// locate the task
DmFindRecordByID(dbP, uniqueID, &gActualTask);
// update the table, because if the task moved down has children, its
// new index is not in the table, and SelectTask will crash with
// move = true
ProjectTableUpdate();
return pgOK;
} // pgErr TaskDown(UInt16 index)
/****************************************************************************
* Name : TaskPublishToDo
* Desc : publish the actual task in the ToDo DB
* Prm :
* Out :
* Auth : lb, 21.08.2000
***************************************************************************/
pgErr TaskPublishToDo(DmOpenRef dbP, UInt16 index)
{
DmOpenRef ToDoDB;
ToDoItemType task;
MemHandle h;
TaskRecordType *p;
UInt16 todoIndex = 0;
Err err = errNone;
UInt32 uniqueID;
TaskFormatType format;
if (TaskGetFormat(dbP, index).hasToDo)
return pgOK;
// try to open the ToDo database
if (ToDoGetDatabase(&ToDoDB, dmModeReadWrite))
{
FrmCustomAlert(AltEmpty, "Can't open the todo database", "", "");
return pgError;
}
h = DmQueryRecord(dbP, index);
if (!h)
return pgError;
p = MemHandleLock(h);
// convert due date format if there's no due date
task.dueDate = p->dueDate;
if (task.dueDate.month == 0)
{
*((UInt16 *) &task.dueDate) = toDoNoDueDate;
}
// convert priority : no => 5
task.priority = p->priority;
if (!(task.priority > 0 && task.priority < 6))
{
task.priority = 5;
}
task.description = &p->description;
task.note = "";
MemHandleUnlock(h);
err = ToDoNewRecord(ToDoDB, &task, 0, &todoIndex);
if (err == errNone)
{
DmRecordInfo(ToDoDB, todoIndex, NULL, &uniqueID, NULL);
TaskSetExtraChunk(dbP, index, Extra_Link_ToDo, 0x00,
&uniqueID, sizeof(uniqueID));
format = TaskGetFormat(dbP, index);
format.hasToDo = 1;
TaskSetFormat(dbP, index, format);
}
else
{
DEBUG1("Export failed !");
}
DmCloseDatabase(ToDoDB);
return pgOK;
} // pgErr TaskPublishToDo(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSetToDoStatus
* Desc : update the sync todo
* Prm :
* -> database
* -> index of task
* -> field to update in : (one at a time)
* toDoPriority,
* toDoComplete,
* toDoDueDate,
* toDoDescription, not yet
* toDoNote, not yet
* toDoCategory, not yet
* -> value (pass NULL if you don't want it)
* -> priority (")
* -> duedate (")
* Out :
* Auth : lb, 30.08.2000
***************************************************************************/
pgErr TaskSetToDoStatus(DmOpenRef dbP, UInt16 index, UInt16 field,
UInt8 value, UInt16 priority, DateType dueDate)
{
DmOpenRef ToDoDB;
UInt32 uniqueID;
UInt16 todoIndex;
UInt16 zero = 0, one = 1;
Err err;
uniqueID = TaskGetToDoUniqueID(dbP, index);
if (!uniqueID)
return pgError;
// try to open the ToDo database
if (ToDoGetDatabase(&ToDoDB, dmModeReadWrite))
{
FrmCustomAlert(AltEmpty, "Can't open the todo database", "", "");
return pgError;
}
if (DmFindRecordByID(ToDoDB, uniqueID, &todoIndex))
{
DmCloseDatabase(ToDoDB);
DEBUG1("The corresponding ToDo was not found, removing link.");
TaskRemoveHasToDo(dbP, index);
return pgError;
}
if (field == toDoPriority)
{
if (priority > 5 || priority < 1)
priority = 5;
err = ToDoChangeRecord(ToDoDB, &todoIndex, toDoPriority,
&priority);
}
if (field == toDoComplete)
{
err = ToDoChangeRecord(ToDoDB, &todoIndex, toDoComplete,
value == ACTION_OK ? &one : &zero );
}
if (field == toDoDueDate)
{
if (dueDate.month == 0)
*((UInt16 *) &dueDate) = toDoNoDueDate;
err = ToDoChangeRecord(ToDoDB, &todoIndex, toDoDueDate,
(UInt16*)&dueDate);
}
//ToDoRecordFieldType
//typedef enum {
//toDoPriority,
//toDoComplete,
//toDoDueDate,
//toDoDescription,
//toDoNote,
//toDoCategory } ToDoRecordFieldType;
//
//#define completeFlag 0x80
//#define priorityOnly ~completeFlag
DmCloseDatabase(ToDoDB);
return pgOK;
} // pgErr TaskSetToDoStatus(DmOpenRef dbP, UInt16 index, UInt16 fields,
// UInt8 value, UInt8 priority, DateType dueDate)
/****************************************************************************
* Name : TaskUpdateToDo
* Desc : update the values of the ToDo
* Prm :
* -> database
* -> index of task
* <- value (pass NULL if you don't want it)
* <- priority (")
* <- duedate (")
* Out :
* Auth : lb, 30.08.2000
***************************************************************************/
Err TaskUpdateToDo(DmOpenRef dbP, UInt16 index)
{
Err err = errNone;
// see if we're synchronized with a ToDo
if (TaskGetFormat(dbP, index).hasToDo)
{
Err err;
// check the status in ToDo and update this task
err = TaskSetToDoStatus(dbP, index, toDoComplete,
TaskGetCompleted(dbP, index),
0, gNoDate);
err = TaskSetToDoStatus(dbP, index, toDoDueDate,
0, 0,
TaskGetDueDate(dbP, index));
err = TaskSetToDoStatus(dbP, index, toDoPriority,
0,
TaskGetPriority(dbP, index),
gNoDate);
}
return err;
} // Err TaskUpdateToDo(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskSyncAll
* Desc : Update all the todo linked tasks
* Prm :
* Out :
* Auth : lb, 30.08.2000
***************************************************************************/
void TaskSyncAll(void)
{
UInt16 numRec = DmNumRecords(gdbP);
UInt16 i;
DateType dueDate;
UInt8 value, priority;
for (i = 1; i < numRec; i++)
{
// see if we're synchronized with a ToDo
if (TaskGetFormat(gdbP, i).hasToDo)
{
pgErr err;
// check the status in ToDo and update this task
err = TaskGetToDoStatus(gdbP, i,
&value, &priority, &dueDate);
if (err == pgOK)
{
TaskSetCompleted(gdbP, i, value);
TaskSetDueDate(gdbP, i, dueDate);
TaskSetPriority(gdbP, i, priority);
}
}
}
} // void TaskSyncAll(void)
/****************************************************************************
* Name : TaskRemoveHasToDo
* Desc : remove the todo link
* Prm :
* -> database
* -> index of task
* Out :
* Auth : lb, 30.08.2000
***************************************************************************/
pgErr TaskRemoveHasToDo(DmOpenRef dbP, UInt16 index)
{
TaskFormatType format;
//MemPtr p;
//UInt32 size
UInt32 uniqueID;
// update the format field
format = TaskGetFormat(dbP, index);
if (format.hasToDo == 0)
return pgOK;
uniqueID = TaskGetToDoUniqueID(dbP, index);
format.hasToDo = 0;
TaskSetFormat(dbP, index, format);
if (uniqueID)
{
DmOpenRef ToDoDB;
UInt16 todoIndex;
// try to open the ToDo database
if (ToDoGetDatabase(&ToDoDB, dmModeReadWrite))
{
FrmCustomAlert(AltEmpty, "Can't open the todo database", "", "");
return pgError;
}
if (DmFindRecordByID(ToDoDB, uniqueID, &todoIndex))
{
DmCloseDatabase(ToDoDB);
return pgError;
}
DmRemoveRecord(ToDoDB, todoIndex);
DmCloseDatabase(ToDoDB);
}
TaskRemoveExtraChunk(dbP, index, Extra_Link_ToDo, 0xff);
return pgOK;
} // pgErr TaskRemoveHasToDo(DmOpenRef dbP, UInt16 index)
/****************************************************************************
* Name : TaskGetToDoStatus
* Desc : check the value of this task in the ToDo database
* Prm :
* -> database
* -> index of task
* <- value (pass NULL if you don't want it)
* <- priority (")
* <- duedate (")
* Out :
* Auth : lb, 30.08.2000
* Mod : lb, 10.09.2000
* - forgot to unlock the handle, fixed
***************************************************************************/
pgErr TaskGetToDoStatus(DmOpenRef dbP, UInt16 index, UInt8 *value,
UInt8 *priority, DateType *dueDate)
{
DmOpenRef ToDoDB;
MemHandle h;
ToDoDBRecord *p;
UInt32 uniqueID;
UInt16 todoIndex;
UInt16 attr;
uniqueID = TaskGetToDoUniqueID(dbP, index);
if (!uniqueID)
return pgError;
// try to open the ToDo database
if (ToDoGetDatabase(&ToDoDB, dmModeReadWrite))
{
FrmCustomAlert(AltEmpty, "Can't open the todo database", "", "");
return pgError;
}
if (DmFindRecordByID(ToDoDB, uniqueID, &todoIndex))
{
DmCloseDatabase(ToDoDB);
return pgError;
}
DmRecordInfo(ToDoDB, todoIndex, &attr, NULL, NULL);
if (attr & dmRecAttrDelete)
{
DmCloseDatabase(ToDoDB);
TaskRemoveHasToDo(dbP, index);
return pgError;
}
// from ToDo files
//typedef struct {
//DateType dueDate;
//UInt8 priority; // high bit is complete flag
//char description;
//} ToDoDBRecord;
//#define completeFlag 0x80
//#define priorityOnly ~completeFlag
h = DmQueryRecord(ToDoDB, todoIndex);
p = MemHandleLock(h);
if (value)
*value = p->priority & completeFlag ? ACTION_OK : ACTION_NO;
if (priority)
*priority = p->priority & priorityOnly;
if (dueDate)
{
*dueDate = p->dueDate;
if (*((UInt16 *) dueDate) == toDoNoDueDate)
{
dueDate->month = 0;
dueDate->year = 0;
dueDate->day = 0;
}
}
MemHandleUnlock(h);
DmCloseDatabase(ToDoDB);
return pgOK;
} // pgErr TaskGetToDoStatus(DmOpenRef dbP, UInt16 index, UInt8 *value,
// UInt8 *priority, DateType *dueDate)
/****************************************************************************
* Name : TaskRepairTree
* Desc : try to repair a broken tree
* Prm :
* -> start : first index to correct (0 to correct all tree)
* -> end : last index to correct (max numrec - 1)
* Out :
* Auth : lb, 30.08.2000
***************************************************************************/
pgErr TaskRepairTree(DmOpenRef dbP, UInt16 start, UInt16 stop)
{
UInt16 index = 1, numRec = DmNumRecords(dbP);
UInt8 level, nextLevel;
UInt16 t;
if (numRec < 2)
return pgError;
// this is true in all cases
TaskSetHasPrev(dbP, 1, false);
TaskSetHasNext(dbP, numRec - 1, false);
TaskSetHasChild(dbP, numRec - 1, false);
if (start == 0)
{
// ensure a good start
TaskSetLevel(dbP, 1, 1);
// correct the levels + hasChild status
for (index = 1; index < numRec - 1; index++)
{
level = TaskGetLevel(dbP, index);
nextLevel = TaskGetLevel(dbP, index + 1);
if (nextLevel == 0)
{
nextLevel = 1;
}
if (nextLevel > level)
{
TaskSetLevel(dbP, index + 1, level + 1);
TaskSetHasChild(dbP, index, true);
}
else
{
TaskSetHasChild(dbP, index, false);
}
}
start = 1;
stop = numRec - 1;
}
else
{
if (stop > numRec - 1)
stop = numRec - 1;
}
// correct the hasNext + hasPrev status
for (index = start; index < stop; index++)
{
level = TaskGetLevel(dbP, index);
nextLevel = TaskGetLevel(dbP, index + 1);
if (nextLevel == level)
{
TaskSetHasNext(dbP, index, true);
TaskSetHasPrev(dbP, index + 1, true);
}
else if (nextLevel < level)
{
TaskSetHasNext(dbP, index, false);
}
else
{
TaskSetHasPrev(dbP, index + 1, false);
// need to search if there's a next below
t = index + 1;
while((t < numRec - 1) && TaskGetLevel(dbP, t) > level)
{
t++;
}
if (TaskGetLevel(dbP, t) == level)
{
TaskSetHasNext(dbP, index, true);
TaskSetHasPrev(dbP, t, true);
}
else
{
TaskSetHasNext(dbP, index, false);
}
}
}
return pgOK;
} // pgErr TaskRepairTree(DmOpenRef dbP, UInt16 start, UInt16 stop)
/****************************************************************************
* Name : TaskToClipboard
* Desc : copy the given task (with children) to the clipboard
* Prm :
* -> database pointer
* -> index of the task to copy
* -> true => copy parent too
* Out :
* Auth : lb, 04.09.2000
***************************************************************************/
pgErr TaskToClipboard(DmOpenRef dbP, UInt16 index, Boolean withParent)
{
UInt16 clipIndex = 0, i = index, numRec = DmNumRecords(dbP);
UInt8 refLevel, level = 0;
MemHandle hSrc, hClip;
TaskRecordType *pSrc, *pClip;
Err err;
err = NewClipboard();
if (err)
{
DEBUG1("Cannot create the clipboard, copy canceled.");
return pgError;
}
refLevel = TaskGetLevel(dbP, index);
// if we don't want the parent, begin at next one
if (!withParent)
{
i++;
}
// copy the task and all its children
while ((i < numRec && (level = TaskGetLevel(dbP, i)) > refLevel) ||
i == index)
{
clipIndex = dmMaxRecordIndex; // add to the end of the clip
hSrc = DmQueryRecord(dbP, i);
pSrc = MemHandleLock(hSrc);
hClip = DmNewRecord(gClip, &clipIndex, MemPtrSize(pSrc));
MemHandleUnlock(hSrc);
pSrc = MemHandleLock(hSrc);
pClip = MemHandleLock(hClip);
DmWrite(pClip, 0, pSrc, MemPtrSize(pSrc));
MemHandleUnlock(hClip);
MemHandleUnlock(hSrc);
DmReleaseRecord(gClip, clipIndex, true);
// adapt the level
TaskSetLevel(gClip, clipIndex, level - refLevel + 1);
// next record
i++;
}
CloseClipboard();
return pgOK;
} // pgErr TaskToClipboard(DmOpenRef dbP, UInt16 index, Boolean withParent)
/****************************************************************************
* Name : TaskFromClipboard
* Desc : copy the clipboard as a brother of the given task
* Prm :
* -> database pointer
* -> index of the brother task
* -> true to paste as children of the given task
* Out :
* Auth : lb, 04.09.2000
***************************************************************************/
pgErr TaskFromClipboard(DmOpenRef dbP, UInt16 index, Boolean asChildren)
{
UInt16 numRec, i = 1, insertIndex = index;
TaskRecordType *pClip, *pDest;
MemHandle hClip, hDest;
UInt8 refLevel = 0;
Err err;
err = OpenClipboard();
if (err)
{
DEBUG1("Cannot open the clipboard, paste canceled.");
return pgError;
}
if ((numRec = DmNumRecords(gClip)) < 2)
{
CloseClipboard();
DEBUG1("Clipboard empty");
return pgOK;
}
// insert after selected one, as a brother
index = TaskGetNextRelativeIndex(dbP, index);
if (!index)
index = dmMaxRecordIndex;
while (i < numRec)
{
hClip = DmQueryRecord(gClip, i);
pClip = MemHandleLock(hClip);
hDest = DmNewRecord(dbP, &index, MemPtrSize(pClip));
// reget handle (chunk could have moved, I think...)
MemHandleUnlock(hClip);
pClip = MemHandleLock(hClip);
pDest = MemHandleLock(hDest);
DmWrite(pDest, 0, pClip, MemPtrSize(pClip));
MemHandleUnlock(hDest);
DmReleaseRecord(dbP, index, true);
MemHandleUnlock(hClip);
if (i == 1)
{
if (asChildren)
{
TaskSetLevel(dbP, index,
(refLevel = TaskGetLevel(dbP, insertIndex) + 1));
refLevel -= TaskGetLevel(gClip, 1);
TaskSetHasChild(dbP, insertIndex, true);
}
else
{
TaskSetLevel(dbP, index,
(refLevel = TaskGetLevel(dbP, insertIndex)));
refLevel -= TaskGetLevel(gClip, 1);
}
}
else
{
TaskSetLevel(dbP, index, pClip->attr.bits.level + refLevel);
}
i++;
index++;
}
// TODO : this can cause crash when :
// - copying a task that has children but no next
// - paste it as a brother of a task that has a next
// => pasted task has flag no next, but has one => graphical problem
// => crash when trying to delete it
//TaskRepairTree(gdbP, insertIndex, insertIndex + numRec);
// the constrained repair doesn't seem to work well with this case
TaskRepairTree(gdbP, 0, 0); // this cause a complete repair, it's slow
CloseClipboard();
return pgOK;
} // pgErr TaskFromClipboard(DmOpenRef dbP, UInt16 index, Boolean asChildren)
/****************************************************************************
* Name : TaskFindExtraChunk
* Desc : find chunk of extra block
* Prm :
* -> extra block ptr
* -> chunk type
* -> sub key. 0xff is wild.
* Out : headder of it chunk if type was found, otherwith return NULL.
* Auth : seagull, 27,09,2000
***************************************************************************/
static ExtraChunkHeadType*
TaskFindExtraChunkHead(ExtraChunkHeadType* block,
UInt8 type, UInt8 subkey)
{
// NOTE: if type is NULL, this function must be find NULL block.
// see TaskSetExtraChunk
for (;;)
{
if (block->type == type &&
(subkey == 0xff || block->subkey == subkey))
return block;
else if (block->type == Extra_NULL)
return NULL;
block = NextChunk(block);
}
} //static ExtraChunkHeadType*
//TaskFindExtraChunkHead(ExtraChunkHeadType const* block,
// UInt8 type, UInt8 subkey)
/****************************************************************************
* Name : TaskGetExtraChunk
* Desc : get chunk data of extra block
* Prm :
* -> database ptr
* -> index
* -> chunk type
* -> subkey
* -> buffer ptr
* -> size ptr
* Out : retrieve body to dest if not NULL and chunk is found.
* set *size to chunk size in bytes.
* return pgOK if chunk was found and buffer size is enoth,
* otherwith return pgError.
* Auth : seagull, 27,09,2000
***************************************************************************/
pgErr TaskGetExtraChunk(DmOpenRef dbP, UInt16 index, UInt8 type, UInt8 subkey,
MemPtr dest, UInt16* size/*in bytes*/)
{
MemHandle hTask = DmQueryRecord(dbP, index);
pgErr err = TaskGetExtraChunkByTaskPtr(
(TaskExtendedRecordType*)MemHandleLock(hTask),
type, subkey, dest, size);
MemHandleUnlock(hTask);
return err;
}//pgErr TaskGetExtraChunk(DmOpenRef dbP, UInt16 index, UInt8 type, UInt8 subkey
// MemPtr dest, UInt16* size/*in bytes*/)
/****************************************************************************
* Name : TaskGetExtraChunkByTaskPtr
* Desc : get chunk data of extra block
* Prm :
* -> Task ptr
* -> chunk type
* -> subkey
* -> buffer ptr
* -> size ptr
* Out : retrieve body to dest if not NULL and chunk is found.
* set *size to chunk size in bytes.
* return pgOK if chunk was found and buffer size is enoth,
* otherwith return pgError.
* Auth : seagull, 27,09,2000
***************************************************************************/
pgErr TaskGetExtraChunkByTaskPtr(TaskExtendedRecordType* pTask,
UInt8 type, UInt8 subkey,
MemPtr dest, UInt16* size/*in bytes*/)
{
pgErr err = pgError;
ExtraChunkHeadType* pChunk =
(ExtraChunkHeadType*)TaskGetExtraBlockHeadPtr(pTask);
if ((MemPtr)pTask + MemPtrSize(pTask) - (MemPtr)pChunk
> sizeof(ExtraChunkHeadType) * 2)
{
pChunk = TaskFindExtraChunkHead(pChunk, type, subkey);
if (pChunk != NULL && size != NULL)
{
if (dest != NULL && pChunk->size <= *size)
{
MemMove(dest, pChunk->body, pChunk->size);
err = pgOK;
}
*size = pChunk->size;
}
else if (size == NULL)
err = pgOK; // return exist/non exist status only.
}
return err;
} //pgErr TaskGetExtraChunkByTaskPtr(TaskExtendedRecordType* pTask,
// UInt8 type, UInt8 subkey,
// MemPtr dest, UInt16* size/*in bytes*/)
/****************************************************************************
* Name : TaskRemoveExtraChunk
* Desc : remove chunk and compaction extra block.
* Prm :
* -> databse ptr
* -> index
* -> chunk type
* -> subkey
* Out :
* Auth : seagull, 27,09,2000
***************************************************************************/
void TaskRemoveExtraChunk(DmOpenRef dbP, UInt16 index,
UInt8 type, UInt8 subkey)
{
ExtraChunkHeadType* pChunk;
UInt8* pExtra;
UInt32 sizeExtra = TaskGetExtraBlock(dbP, index, NULL);
if (! sizeExtra) return ; // no bloc
if (sizeExtra < 5) // malformed, destroy it
{
TaskSetExtraBlock(dbP, index, NULL, 0);
return;
}
pExtra = MemPtrNew(sizeExtra);
TaskGetExtraBlock(dbP, index, pExtra);
pChunk = TaskFindExtraChunkHead((ExtraChunkHeadType*)pExtra,
type, subkey);
if (pChunk)
{ // found it, go to compaction
UInt8* src = (UInt8*)NextChunk(pChunk);
UInt8* dst = (UInt8*)pChunk;
UInt16 sizeChunk = (UInt8*)src - (UInt8*)pChunk;
if (((ExtraChunkHeadType*)src)->type == Extra_NULL &&
dst == pExtra)
{ // Extra block is empty. delete it
TaskSetExtraBlock(dbP, index, NULL, 0);
}
else
{
while (src < pExtra + sizeExtra)
*dst++ = *src++;
TaskSetExtraBlock(dbP, index, pExtra, sizeExtra - sizeChunk);
}
}
MemPtrFree(pExtra);
}//void TaskRemoveExtraChunk(DmOpenRef dbP, UInt16 index,
// UInt8 type, UInt8 subkey)
/****************************************************************************
* Name : TaskSetExtraChunk
* Desc :
* Prm :
* -> database ptr
* -> index
* -> chunk type
* -> source buffer
* -> chunk size
* Out :
* Auth : seagull, 27,09,2000
***************************************************************************/
pgErr TaskSetExtraChunk(DmOpenRef dbP, UInt16 index,
UInt8 type, UInt8 subkey,
MemPtr src, UInt16 size)
{
// TODO: reuse block if type, subkey and size is equal.
MemPtr pExtra = NULL;
UInt32 sizeExtra;
ExtraChunkHeadType* pChunk = NULL;
Boolean bCreateNew = true;
TaskRemoveExtraChunk(dbP, index, type, subkey);
sizeExtra = TaskGetExtraBlock(dbP, index, NULL);
if (sizeExtra)
{
pExtra = MemPtrNew(sizeExtra + sizeof(ExtraChunkHeadType) + size);
if (! pExtra) return pgError;
TaskGetExtraBlock(dbP, index, pExtra);
pChunk = TaskFindExtraChunkHead((ExtraChunkHeadType*)pExtra,
Extra_NULL, 0);
if (pChunk)
bCreateNew = false;
else
{
MemPtrFree(pExtra);
DEBUG1("Extra chunk was broken. Deleted");
}
}
if (bCreateNew)
{ // *2 is itself and null chunk
pExtra = MemPtrNew(sizeof(ExtraChunkHeadType) * 2 + size);
if (! pExtra) return pgError;
pChunk = pExtra;
}
// make new chunk
pChunk->type = type;
pChunk->subkey = subkey;
pChunk->size = size;
MemMove(pChunk->body, src, size);
// make new sentinel
pChunk = NextChunk(pChunk);
pChunk->type = Extra_NULL;
pChunk->subkey = 0;
pChunk->size = 0;
TaskSetExtraBlock(dbP, index, pExtra, MemPtrSize(pExtra));
MemPtrFree(pExtra);
return pgOK;
}