⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sugarmemodb.c

📁 Palm上著名的背单词软件的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	
	if (record->field[WordFieldQuestion]!=NULL)
		index += StrLen(record->field[WordFieldQuestion])+1;
	if (record->field[WordFieldPhonetic]!=NULL)
		index += StrLen(record->field[WordFieldPhonetic])+1;
	if (record->field[WordFieldAnswer]!=NULL)
		answerOffset = index;
	
	DmWrite(recordDBEntry, (UInt32)&packed->answerOffset, &answerOffset, sizeof(answerOffset));

}	//end of routine PackRecord

//	unpack word record
static void UnpackRecord(WordPackedRecord *packed, WordRecordType *record){
	Int16 index;
	UInt16 flags;
	char* p;
	
	record->header = packed ->header;
	record->ltStatus = packed ->ltStatus;
	record->memoStatus = packed ->memoStatus;
	flags = packed -> wordDBRecordFlags.allBits;
	p = & packed -> firstField;
	
	for (index = 0; index < WordFieldsCount; index ++){
		if (GetBitMacro(flags, index) != 0){
			record->field[index] = p;
			p += StrLen(p) + 1;
		}
		else{
			record->field[index] = NULL;
		}
	}
}

//	callback funtion for compare records
static Int16 WordDBComparePackedRecords(WordPackedRecord* packed1, WordPackedRecord* packed2,
	Int16 uselessinfo, SortRecordInfoPtr infoP1, SortRecordInfoPtr infoP2, MemHandle appinfoH){
	
	//if both header remain their sequence
	if ((GetBitMacro(packed1->header.allBits, HeaderFlag))
			&& (GetBitMacro(packed2->header.allBits, HeaderFlag)))
		return 0;
	
	//otherwise the header record is less than the other one
	if (GetBitMacro(packed1->header.allBits, HeaderFlag))
		return -1;
	
	if (GetBitMacro(packed2->header.allBits, HeaderFlag))
		return 1;
	
	//both word, and both no question field
	if ((GetBitMacro(packed1->wordDBRecordFlags.allBits, WordFieldQuestion) == 0)
		&& (GetBitMacro(packed2->wordDBRecordFlags.allBits, WordFieldQuestion) == 0))
		return 0;
	
	//both word, the one without question field is less than the other one
	if (GetBitMacro(packed1->wordDBRecordFlags.allBits, WordFieldQuestion) == 0)
		return -1;
	
	if (GetBitMacro(packed2->wordDBRecordFlags.allBits, WordFieldQuestion) == 0)
		return 1;
	
	//both word and both have the question field, compare string
	return StrCaselessCompare((char*)(&packed1->firstField), (char*)(&packed2->firstField));
}

//	create new record
Err NewWordRecord(DmOpenRef db, WordRecordType* record, UInt16* index){
	
	MemHandle recordH;
	WordPackedRecord* packed;
	UInt16 newIndex;
	Err error;
	
	//allocate new record size
	recordH = DmNewHandle(db, WordUnpackedSize(record));
	
	if (recordH == NULL) return dmErrMemError;
	
	//copy the data from unpacked record to packed one
	packed = MemHandleLock(recordH); //locked once
	PackRecord(record, packed);
	
	//get the index of new record
	newIndex = DmFindSortPosition(db, packed, NULL, (DmComparF*)WordDBComparePackedRecords, NULL);
	MemPtrUnlock(packed); //unlocked
	
	//attach new record in place and return the new index
	error = DmAttachRecord(db, &newIndex, recordH, NULL);
	
	if (error)
		MemHandleFree(recordH);
	else
		*index = newIndex;
	
	return error;
}

//	Get Word Record, noting that recordH is locked here, should be unlock else where!
Err GetWordRecord(DmOpenRef db, UInt16 index, WordRecordType* recordP, MemHandle *recordH)
{
	WordPackedRecord *packed;

	*recordH = DmQueryRecord(db, index);
	packed = (WordPackedRecord *) MemHandleLock(*recordH);
	if (packed == NULL)
		return dmErrIndexOutOfRange;

	UnpackRecord(packed, recordP);

	return 0;
}

//	Change Word Record
Err ChangeWordRecord(DmOpenRef dbP, UInt16 *index, WordRecordType* r, WordFieldFlags changedFields)
{
	WordRecordType     src;
	MemHandle          srcH;
	Err                error;
	MemHandle          recordH = 0; ///???
	MemHandle          oldH;
	Int16              i;
	UInt32             changes = changedFields.allBits;
	Boolean            dontMove;
	UInt16             attributes;      // to contain the deleted flag

	WordPackedRecord*   cmpP;
	WordPackedRecord*   recordP;

	// We do not assume that r is completely valid so we get a valid
	// WordRecordType*...
	if ((error = GetWordRecord(dbP, *index, &src, &srcH)) != 0)
		return error;

	// and we apply the changes to it.
	src.header = r->header;         // copy the status
	src.ltStatus = r->ltStatus;
	src.memoStatus = r->memoStatus;
	
	for (i = WordFieldQuestion; i < WordFieldsCount; i++)
	{
		// If the flag is set point to the string else NULL
		if (GetBitMacro(changes, i) != 0)
		{
			src.field[i] = r->field[i];
			RemoveBitMacro(changes, i);
		}
		if (changes == 0)
			break;      // no more changes
	}

	
	// 1) and 2) (make a new chunk with the correct size)
	recordH = DmNewHandle(dbP, WordUnpackedSize(&src));
	if (recordH == NULL)
	{
		MemHandleUnlock(srcH);      // undo lock from GetWordRecord above
		return dmErrMemError;
	}
	recordP = MemHandleLock(recordH);


	// 3) Copy the data from the unpacked record to the packed one.
	PackRecord(&src, recordP);

	// The original record is copied and no longer needed.
	MemHandleUnlock(srcH);


	// 4) if the sort position changes...
	// Check if question field has changed
	if ((changedFields.allBits & BitAtPosition(WordFieldQuestion)) == 0)
		goto attachRecord;

	
	// Make sure *index-1 < *index < *index+1, if so it's in sorted
	// order.  Leave it there.
	//appInfoPtr = (SugarAppInfoType*) GetAppInfoPtr(dbP);
	//sortByCompany = appInfoPtr->misc.sortByCompany;
	//MemPtrUnlock(appInfoPtr);

	if (*index > HeaderIndexCounts)
	{
		// This record wasn't deleted and deleted records are at the end of the
		// database so the prior record may not be deleted!
		cmpP = MemHandleLock(DmQueryRecord(dbP, *index-1));
		dontMove = (WordDBComparePackedRecords (cmpP,  recordP, NULL, NULL, NULL, 0) < 0);
		MemPtrUnlock(cmpP);
	}
	else
		dontMove = true;


	if (*index+1 < DmNumRecords (dbP))
	{
		DmRecordInfo(dbP, *index+1, &attributes, NULL, NULL);
		if (attributes & dmRecAttrDelete)
			;      // don't move it after the deleted record!
		else {
			cmpP = MemHandleLock(DmQueryRecord(dbP, *index+1));
			dontMove = dontMove && (WordDBComparePackedRecords (recordP, cmpP, NULL, NULL, NULL, 0) == -1);
			MemPtrUnlock(cmpP);
		}
	}


	if (dontMove)
		goto attachRecord;



	// The record isn't in the right position.  Move it.
	i = DmFindSortPosition(dbP, recordP, NULL, (DmComparF*)WordDBComparePackedRecords, NULL);
	DmMoveRecord(dbP, *index, i);
	if (i > *index) i--;
	*index = i;                  // return new position


	// Attach the new record to the old index,  the preserves the
	// category and record id.
	
	
attachRecord:

	error = DmAttachRecord(dbP, index, recordH, &oldH);
	MemPtrUnlock(recordP);
	if (error) return error;

	MemHandleFree(oldH);
	
	return 0;
}

// delete word record
void WordDBDeleteRecord(Boolean archive){
	
	HeaderQueue queue = GetQueue(CurrentDB, CurrentRecord);
	
	if (queue == RawQueue) 		DecrementRawWordCount();	
	
	if (queue == LearningQueue) RemoveHeaderItemByDBIndex(CurrentDB, LearningRecordIndex, CurrentRecord);
	if (queue == TestingQueue)  RemoveHeaderItemByDBIndex(CurrentDB, TestingRecordIndex, CurrentRecord);
	RemoveHeaderItemByDBIndex(CurrentDB, TestingChoiceBuffer, CurrentRecord);	
	RemoveHeaderItemByDBIndex(CurrentDB, LearningChoiceBuffer, CurrentRecord);
	
	if (archive)
	{
		DmArchiveRecord (CurrentDB, CurrentRecord);
	}
	else
		DmRemoveRecord (CurrentDB, CurrentRecord);

	CurrentRecord = noRecord;
}

//*******************************************************************
//
//	high-level word record manipulation
//	1.GetQueue();
//	2.SetQueue(HeaderQueue queue);
//	3.GetLearningStatus();
//	4.SetLearningStatus(LearningStatus ls);
//	5.GetTestingStatus();
//	6.SetTestingStatus(TestingStatus ls);
//	7.GetMemorizingStatus();
//	8.SetmemorizingStatus(MemorizingStatus memoStatus);
//
//*******************************************************************


//	Get CurrentRecord Queue
HeaderQueue GetQueue(DmOpenRef db, UInt16 index){

	HeaderQueue queue;
	Header* header;
	MemHandle recordH;
	
	recordH = DmQueryRecord(db, index);
	if (recordH == NULL) return BadQueue;
	
	header = MemHandleLock(recordH);

	if (GetBitMacro(header->allBits, RawQueue))	queue = RawQueue;
	else if (GetBitMacro(header->allBits, LearningQueue)) queue = LearningQueue;
	else if (GetBitMacro(header->allBits, TestingQueue)) queue = TestingQueue;
	else if (GetBitMacro(header->allBits, WaitingQueue)) queue = WaitingQueue;

	else if (GetBitMacro(header->allBits, HeaderFlag) && GetBitMacro(header->allBits, LearningQFlag)) 
		queue = LearningQFlag;
	else if (GetBitMacro(header->allBits, HeaderFlag) && GetBitMacro(header->allBits, TestingQFlag))
		queue = TestingQFlag;
	else if (GetBitMacro(header->allBits, HeaderFlag) && GetBitMacro(header->allBits, LearningBFlag)) 
		queue = LearningBFlag;
	else if (GetBitMacro(header->allBits, HeaderFlag) && GetBitMacro(header->allBits, TestingBFlag))
		queue = TestingBFlag;

	MemHandleUnlock(recordH);
	return queue;
}

//	Set CurrentRecord Queue
void	SetQueue(DmOpenRef db, UInt16 index, HeaderQueue queue){

	WordFieldFlags flag;
	WordRecordType record;
	MemHandle recordH;
	HeaderQueue oldQueue;
	
	oldQueue = GetQueue(db, index);
	
	if (oldQueue == queue) return;
	
	//	remove from old header Q 
	if (oldQueue == LearningQueue) 	RemoveHeaderItemByDBIndex(db, LearningRecordIndex, index);
	if (oldQueue == TestingQueue) 	RemoveHeaderItemByDBIndex(db, TestingRecordIndex, index);
		
	//	add to new header Q
	if (queue == LearningQueue) AddHeaderItemByDBIndex(db, LearningRecordIndex, index);
	if (queue == TestingQueue)	AddHeaderItemByDBIndex(db, TestingRecordIndex, index);
	
	//	update raw word count
	if (oldQueue == RawQueue) DecrementRawWordCount();
	if (queue == RawQueue) IncrementRawWordCount();
	
	flag.allBits = 0;
	
	GetWordRecord(db, index, &record, &recordH);
	record.header.allBits = BitAtPosition(queue);
	ChangeWordRecord(db, &index, &record, flag);

}

//	Get learning status of CurrentRecord
LearningStatus GetLearningStatus(DmOpenRef db, UInt16 index){
	WordRecordType record;
	MemHandle recordH;
	LearningStatus status;
	
	GetWordRecord(db, index, &record, &recordH); //lock recordH
	status = record.ltStatus.learningStatus;
	MemHandleUnlock(recordH);
	
	return status;
}

//	Set learning status of CurrentRecord
void SetLearningStatus(DmOpenRef db, UInt16 index, LearningStatus ls){
	WordFieldFlags flag;
	WordRecordType record;
	MemHandle recordH;
	
	GetWordRecord(db, index, &record, &recordH);
	record.ltStatus.learningStatus = ls;
	flag.allBits = 0;
	ChangeWordRecord(db, &index, &record, flag); 
}

//	Get testing status of CurrentRecord
TestingStatus GetTestingStatus(DmOpenRef db, UInt16 index){
	WordRecordType record;
	MemHandle recordH;
	TestingStatus status;
	
	GetWordRecord(db, index, &record, &recordH); //lock recordH
	status = record.ltStatus.testingStatus;
	MemHandleUnlock(recordH);
	
	return status;
}

//	Set testing status of CurrentRecord
void SetTestingStatus(DmOpenRef db, UInt16 index, TestingStatus ts){
	WordFieldFlags flag;
	WordRecordType record;
	MemHandle recordH;
	
	GetWordRecord(db, index, &record, &recordH);
	record.ltStatus.testingStatus = ts;
	flag.allBits = 0;
	ChangeWordRecord(db, &index, &record, flag); 
}

//	Get memorizing status of CurrentRecord
MemorizingStatus GetMemorizingStatus(DmOpenRef db, UInt16 index){
	WordRecordType record;
	MemHandle recordH;
	MemorizingStatus memoStatus;
	
	GetWordRecord(db, index, &record, &recordH);
	memoStatus = record.memoStatus;
	MemHandleUnlock(recordH);
	return memoStatus;
}

//	Set memorizing status of CurrentRecord
void SetMemorizingStatus(DmOpenRef db, UInt16 index, MemorizingStatus memoStatus){
	WordRecordType record;
	MemHandle recordH;
	WordFieldFlags flag;
	
	flag.allBits = 0;
	GetWordRecord(db, index, &record, &recordH);
	record.memoStatus = memoStatus;
	ChangeWordRecord(db, &index, &record, flag);
}

//*******************************************************************
//
//	Misc function relating to database manipulation
//	1.GetDBList();
//	2.WordRecordContainsData (WordRecordType* recordP);
//	3.InstantLookupPosition(DmOpenRef db, Char* p);
//	4.GetWordQueue(DmOpenRef db, UInt16 index);
//
//*******************************************************************

//	Buil
void InitHeaderBuffer(DmOpenRef db, HeaderIndex BufferIndex){
	
	MemHandle srcH, destH;
	HeaderRecord* srcP, *destP;
	MemPtr offsetP;
	UInt16 bufferNum, srcHeaderIndex, destHeaderIndex; // index; //, i, j;
	UInt32 newSize;
	//HeaderItem item;
	//Err error;

	//	validate	
	//bufferNum = GetHeaderItemNumber(db, BufferIndex);
	//for (i = 0; i < bufferNum; i++){
		
		//j = bufferNum -i - 1;
		//if (!GetHeaderItem(db, BufferIndex, &item, j)) continue;
		
		//error = DmFindRecordByID(db, item, &index);
		//if (error)	RemoveHeaderItem(db, BufferIndex, bufferNum - i - 1);

	//}

	bufferNum = GetHeaderItemNumber(db, BufferIndex);
		
	if (bufferNum > 0) return;
	
	if (BufferIndex == LearningChoiceBuffer){
		srcHeaderIndex = LearningRecordIndex;
		destHeaderIndex = LearningChoiceBuffer;	
	}
	
	else if (BufferIndex == TestingChoiceBuffer){
	
		if (GetHeaderItemNumber(db, LearningChoiceBuffer) > 0) 
			srcHeaderIndex = LearningChoiceBuffer;
		else if (GetHeaderItemNumber(db, TestingRecordIndex) > 0) 
			srcHeaderIndex = TestingRecordIndex;
			
		destHeaderIndex = TestingChoiceBuffer;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -