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

📄 sugarmemodb.c

📁 Palm上著名的背单词软件的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		RemoveHeaderItem(db, headerIndex, random);
		
		i++;
		number--;
	}
	
	error = DmAttachRecord(db, &headerIndex, recordH, &oldH);
	
	MemPtrUnlock(destP);
	
	if (error){
	
		MemHandleFree(recordH);
		return false;
	
	}
	
	MemHandleFree(oldH);
	
	return true;
}*/


//remove the i th item in queue
Boolean RemoveHeaderItem(DmOpenRef db, HeaderIndex headerIndex, UInt16 i){

	MemHandle recordH, oldH;
	MemPtr destP;
	HeaderItem* itemP;
	HeaderRecordHelper* srcP;
	HeaderRecordHelper* p = 0;
	UInt16 numbers, size, newSize, offset;
	Err error;
	
	//calculate newsize
	numbers = GetHeaderItemNumber(db, headerIndex);
	size = sizeof(HeaderRecord) + numbers * sizeof(HeaderItem);
	
	newSize = size - sizeof(HeaderItem);
	
	//get original learning record
	srcP = (HeaderRecordHelper*)MemHandleLock(DmQueryRecord(db, headerIndex));	//src locked
	
	//allocate new record			
	recordH = DmNewHandle(db, newSize);
	if (recordH == NULL) return false;
	
	destP = MemHandleLock(recordH);	//dest locked
	
	//copy original data before item i
	DmWrite(destP, 0, srcP, sizeof(HeaderRecord) + i * sizeof(HeaderItem));

	//copy orginal data after item i, if any
	if (i != (numbers - 1)){
		itemP = &srcP->firstItem;
		itemP += i + 1;
		offset = (UInt32)&p->firstItem + i * sizeof(HeaderItem);
		DmWrite(destP, offset, itemP, (numbers - i - 1) * sizeof(HeaderItem));
	}
	//write new number
	numbers--;
	DmWrite(destP, (UInt32)&p->itemNumbers, &numbers, sizeof(numbers));
		
	//unlock src pointer
	MemPtrUnlock(srcP);
	
	//attach new record
	error = DmAttachRecord(db, &headerIndex, recordH, &oldH);
	
	//unlock dest pointer
	MemPtrUnlock(destP);
	
	if (error) {
		MemHandleFree(recordH);
		return false;
	}
	
	//release orphan data
	MemHandleFree(oldH);
	
	return true;
}

// 
Boolean FindHeaderItemByID(DmOpenRef db, HeaderIndex headerIndex, UInt32 uniqueID, UInt16* indexP){

	MemHandle recordH;
	HeaderRecordHelper* recordP;
	HeaderItem* p;
	UInt16 numbers, i = 0;
	Boolean found = false;
	
	recordH = DmQueryRecord(db, headerIndex);
	if (recordH == NULL) return false;
	
	recordP = (HeaderRecordHelper*)MemHandleLock(recordH);
	numbers = recordP -> itemNumbers;
	
	p = &recordP -> firstItem;
	while (i < numbers){
		if ((UInt32)(*p)== uniqueID) {
			found = true;
			break;
		}
		p++;
		i++;
	}
	
	MemPtrUnlock(recordP);
	
	if (found) {
		(*indexP) = i;
		return true;
	}
	
	return false;
}

Boolean FindHeaderItemByDBIndex(DmOpenRef db, HeaderIndex headerIndex, UInt16 dbIndex, UInt16* indexP){

	HeaderItem item;
	
	DmRecordInfo(db, dbIndex, NULL, &item, NULL);
	
	return FindHeaderItemByID(db, headerIndex, item, indexP);

}

//	remove header item according item content, i.e. unique ID
Boolean RemoveHeaderItemByID(DmOpenRef db, HeaderIndex headerIndex, UInt32 uniqueID){
	
	UInt16 i;
	
	if (FindHeaderItemByID(db, headerIndex, uniqueID, &i)) return RemoveHeaderItem(db, headerIndex, i);

	return false;
}

//remove header item by database index
Boolean RemoveHeaderItemByDBIndex(DmOpenRef db, HeaderIndex headerIndex, UInt16 dbIndex){

	HeaderItem item;
	
	DmRecordInfo(db, dbIndex, NULL, &item, NULL);
	
	return RemoveHeaderItemByID(db, headerIndex, item);
}

//remove the first one, insert it into certain position, the status changed in LTStatus
Boolean MoveHeaderItem(DmOpenRef db, HeaderIndex headerIndex, UInt16 index){

	MemHandle recordH;
	HeaderRecordHelper* recordP;
	HeaderItem* p;
	HeaderItem item0;
	UInt16 i;
	
	//check index range
	if (index > GetHeaderItemNumber(db, headerIndex) - 1)
		index = GetHeaderItemNumber(db, headerIndex) - 1;
	
	//save first item
	GetHeaderItem(db, headerIndex, &item0, 0);
	
	recordH = DmQueryRecord(db, headerIndex);
	if (recordH == NULL) return false;
	
	recordP = (HeaderRecordHelper*)MemHandleLock(recordH);
	
	//point to item 1, the second item
	p = &recordP -> firstItem;
	p++; //pointer to item 1
	
	//move 
	for (i = 0; i < index; i++){
		DmWrite(recordP, (sizeof(HeaderRecord) + i * sizeof(HeaderItem)), p, sizeof(HeaderItem));
		p++;
	}
	
	//restore first item
	DmWrite(recordP, (sizeof(HeaderRecord) + index * sizeof(HeaderItem)), &item0, sizeof(HeaderItem));
	
	MemPtrUnlock(recordP);
		
	return true;
}

//	rebuild testing queue
void RebuildTestingQueue(DmOpenRef db, Boolean forced){
	
	UInt16 j, num;
	UInt16 rawWordCount = 0;
	DateType today;
	
	WordPackedRecord* packed;
	MemHandle recordH;
	HeaderItem	item;
	
	SugarAppInfoType* app;
	SugarAppInfoType* appHelper = 0;
	
	Header flag;

	UInt32 progress = 0;
	UInt32 newProgress;
	Char title[dmDBNameLength + 20];
	Char dbName[dmDBNameLength + 1] = "Unknown";
	LocalID localID;
	Err error;
		
	
	DateSecondsToDate(TimGetSeconds(), &today);
	
	app = GetAppInfoPtr(db);
	if (app == NULL) {
		DoCustomDialog("错误", "无法打开AppInfo", false, 0, NULL, false);;		
		return;
	}
	
	if (!forced){
		if (DateToDays(app->lastUpdated) == DateToDays(today)) {
			MemPtrUnlock(app);
			return;
		}
	}		
	
	ClearHeaderRecord(db, TestingRecordIndex);
				
	//loop records
	num = DmNumRecordsInCategory(db, dmAllCategories);
	
	if (num > FirstWordRecord) {
		error = DmOpenDatabaseInfo(db, &localID, NULL, NULL, NULL, NULL);
		
		if (error) ErrAlert(error);
		else {
			
			error = DmDatabaseInfo(0, localID, dbName, NULL, NULL, NULL, NULL, NULL, 
				NULL, NULL, NULL, NULL, NULL);
		
			if (error) ErrAlert(error);
			else StrPrintF(title, "%s %s", "Updating", dbName);
			
		}
		ProgressPie(progress, title);
	}		
	
	for (j = FirstWordRecord; j < num; j++){
			
		recordH = DmQueryRecord(db, j);
		if (recordH == NULL) ErrAlert(DmGetLastErr());
		else {
		
			packed = MemHandleLock(recordH);
			flag.allBits = packed -> header.allBits;
			
			if (GetBitMacro(flag.allBits, RawQueue)) {
				MemHandleUnlock(recordH);
				rawWordCount ++;
			}
				
			else if (GetBitMacro(flag.allBits, TestingQueue)){
				MemHandleUnlock(recordH);
				DmRecordInfo(db, j, NULL, &item, NULL);
				AddHeaderItem(db, TestingRecordIndex, &item);
			}
			
			else if (GetBitMacro(flag.allBits, WaitingQueue)){	
				
				//	if set queue before unlock mem, free handle error !
				if (DateToDays(packed -> memoStatus.nextTest) <= DateToDays(today)){
					MemHandleUnlock(recordH);
					SetQueue(db, j, TestingQueue);
					//DmRecordInfo(db, j, NULL, &item, NULL);
					//AddHeaderItem(db, TestingRecordIndex, &item);
				}
				else MemHandleUnlock(recordH);
			}
			
			//MemHandleUnlock(recordH);
		}
		
		newProgress = (j - 1) * ProgressFull / (num - FirstWordRecord);
		if (newProgress != progress) {
			progress = newProgress;
			ProgressPie(progress, title);
		}
	}
	
	ShuffleHeaderItem(db, TestingRecordIndex);
		
	//updage sugar db app info
	DmWrite(app, (UInt32)&appHelper->lastUpdated, &today, sizeof(today));
	DmWrite(app, (UInt32)&appHelper->rawWordCount, &rawWordCount, sizeof(rawWordCount));
	MemPtrUnlock(app);		
		
}

//	rebuild learning queue
void RebuildLearningQueue(DmOpenRef db){

	MemHandle recordH;
	WordPackedRecord* packed;
	WordPackedRecord* helper = 0;
	LearningStatus ls = FirstLook;
	HeaderItem item;
	UInt16 j;
	UInt16 num;
	
	//clear Learing record
	ClearHeaderRecord(db, LearningRecordIndex);
		
	//loop records
	num = DmNumRecordsInCategory(db, dmAllCategories);
	for (j = FirstWordRecord; j < num; j++){
			
		recordH = DmQueryRecord(db, j);
		packed = MemHandleLock(recordH);
		
		if (GetBitMacro(packed->header.allBits, LearningQueue)){
			DmRecordInfo (db, j, NULL, &item, NULL);
			AddHeaderItem(db, LearningRecordIndex, &item);
			DmWrite(packed, (UInt32)&helper -> ltStatus.learningStatus, &ls, sizeof (LearningStatus));
		}
					
		MemHandleUnlock(recordH);
	}
}

void ResetDatabase(DmOpenRef db){
	
	SugarAppInfoType* app;
	SugarAppInfoType* helper = 0;
	WordPackedRecord packed;
	MemHandle recordH;
	MemPtr p;
	UInt16 j, num;
	UInt32 progress = 0;
	UInt32 newProgress;
	char progressTitle[20] = "Clearing....";
	
	MemSet(&packed, sizeof(packed), 0);
	
	SetBitMacro(packed.header.allBits, RawQueue);
	packed.memoStatus.eFactor = 2.5;
	packed.memoStatus.difficulty = 40;
	
	app = GetAppInfoPtr(db);
	num = DmNumRecordsInCategory(db, dmAllCategories);
	
	if (num > FirstWordRecord) ProgressPie(progress, progressTitle);
	
	for (j = FirstWordRecord; j < num; j++){
	
		recordH = DmQueryRecord(db, j);
		p = MemHandleLock(recordH);
	
		DmWrite(p, 0, &packed,  
			//header + LTStatus + MemorizingStatus - CreateDate (createDate not changed)
			sizeof(Header) + sizeof(LTStatus) + sizeof(MemorizingStatus) - sizeof(DateType));
			
		MemHandleUnlock(recordH);
		
		newProgress = (j - 1) * ProgressFull / (num - FirstWordRecord);
		if (newProgress != progress) {
			progress = newProgress;
			ProgressPie(progress, progressTitle);
		}
	}
	if (num > FirstWordRecord) num -= FirstWordRecord;
	else num = 0;
	
	DmWrite(app, (UInt32)&helper -> rawWordCount, &num, sizeof(num));
	
	MemPtrUnlock(app);
	
	ClearHeaderRecord(db, LearningRecordIndex);
	ClearHeaderRecord(db, TestingRecordIndex);
	ClearHeaderRecord(db, LearningChoiceBuffer);
	ClearHeaderRecord(db, TestingChoiceBuffer);
}

//*******************************************************************
//
//	Word record manipulation
//	1.WordUnpackedSize(WordRecordType *record);
//	2.PackRecord(WordRecordType *record, MemPtr recordDBEntry);
//	3.UnpackRecord(WordPackedRecord *packed, WordRecordType *record);
//	4.WordDBComparePackedRecords(WordPackedRecord * packed1, WordPackedRecord * packed2,
//		Int16 uselessinfo, SortRecordInfoPtr infoP1, SortRecordInfoPtr infoP2, MemHandle appinfoH);
//
//	5.NewWordRecord(DmOpenRef db, WordRecordType* record, UInt16* index);
//	6.GetWordRecord(DmOpenRef db, UInt16 index, WordRecordType* recordP, MemHandle *recordH);
//	7.WordDBDeleteRecord(Boolean archive);
//	8.ChangeWordRecord(DmOpenRef dbP, UInt16 *index, WordRecordType* r, WordFieldFlags changedFields);
//
//*******************************************************************


//	calculate the unpacked record size
static UInt16 WordUnpackedSize(WordRecordType *record){

	UInt16 size;
	int i;
	
	//initial size is the size of a packed record, minus a placeholder of first field
	size = sizeof(WordPackedRecord) - sizeof(char);
	
	for (i = 0; i < WordFieldsCount; i++){
		if (record->field[i] != NULL)
			size += StrLen(record->field[i])+1;
	}
	
	return size;
}

//	pack a record
static void PackRecord(WordRecordType *record, MemPtr recordDBEntry){
	UInt32 offset;
	Int16 index;
	UInt16 length;
	MemPtr p;
	WordFieldFlags flags;
	WordPackedRecord *packed = 0;		//set the pointer to zero! this pointer is used to calculate offset position,
													//NEVER try to use this pointer to access data, will cause fatal error!
	
	UInt16 answerOffset = 0;
	
	flags.allBits = 0;
	
	//write wordstatus first, noting that (UInt32)&packed->wordStatus convert the reference pointer to a UInt32 number,
	//since the packed address is originally set to zero, &packed->wordStatus point to the starting position of 
	//wordStatus, which is zero also at this time. Dangerous but efficient usage!
	 
	DmWrite(recordDBEntry, (UInt32)&packed->header, &record->header, sizeof(record->header));
	DmWrite(recordDBEntry, (UInt32)&packed->ltStatus, &record->ltStatus, sizeof(record->ltStatus));
	DmWrite(recordDBEntry, (UInt32)&packed->memoStatus, &record->memoStatus, sizeof(record->memoStatus));
	
	//pointer to first field placeholder
	offset = (UInt32)&packed->firstField;
	
	//write all fields into record and set the flag bit
	for (index = WordFieldQuestion; index < WordFieldsCount; index++){
		if (record->field[index]!=NULL){
		p = record->field[index];
		length = StrLen(p)+1;
		DmWrite(recordDBEntry, offset, p, length);
		offset += length;
		SetBitMacro(flags.allBits, index);
		}
	
	}	//end of loop
	
	//write flags
	DmWrite(recordDBEntry, (UInt32)&packed->wordDBRecordFlags, &flags.allBits, sizeof(flags.allBits));
	
	//set or clear field offset
	index = 0;

⌨️ 快捷键说明

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