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

📄 sugarmemobrowse.c

📁 Palm上著名的背单词软件的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <PalmOS.h>
#include "SugarMemo.h"
#include "SugarMemoRsc.h"
#include "SugarMemoBrowse.h"
#include "SugarMemoDB.h"
#include "SugarMemoTools.h"

#define statusColumn 	0
#define entryColumn 	1
#define arrowColumn 	2

#define statusColumnWidth 	11
#define arrowColumnWidth 	13
#define columnSpacing 		2

UInt16 		CurrentCategory = dmAllCategories;
Char 		CategoryName[dmCategoryLength];
UInt16      TopVisibleRecord = 0;
Boolean		ShowAllCategories = true;
Int16		VisibleRows = 0;


//*******************************************************************
//	Internal variables
//*******************************************************************

TabSelected 	tabCurrentSelected = StudyListTab;

UInt16 			TopVisibleBackup[TabCounts] = {0, FirstWordRecord, FirstWordRecord};
const Int16 	RowsInTable = 11;
Header 			HeaderMask;

UInt32			SearchFieldTicks = 0;
Boolean			SearchFieldTicking = false;

extern void EditNewRecord();

//*******************************************************************
//	Internal functions
//*******************************************************************
static void 	BrowseFormLoadTable( FormType* frmP );
static void		WordListDrawRecord (void * table, Int16 row, Int16 column, RectanglePtr bounds);
static void 	BrowseFormInit( FormType* frmP );
static void 	ClearWordListTable();

Boolean 		SeekNextRecord(UInt16 * indexP, Int16 direction);
static void 	WordListForward(Boolean byline);
static void 	WordListBackward(Boolean byline);
static UInt16 	WordListSelectCategory (void);
static void 	ToolsChangeCategory (UInt16 category);
static void 	ChangeTab(TabSelected tab);
static void 	DrawTitleBar();
static void 	MoveToStudyList(Int16 row);
static void 	MoveToRawList(Int16 row);
static void 	BatchMoveToStudyList();
static void 	BatchMoveToRawList();
static void 	UpdateSearchField();
static void 	InstantLookup(EventType * event);
static void 	SearchFieldIdle(FieldType* fldP);
static void 	SortStudyList();
static void 	DetectPenDown(EventType* event);
static void 	ShuffleStudyList();
static Char 	WordQueueToChar(HeaderQueue queue);

/////////////////////////////////////////////////
//
//	event handler
//
/////////////////////////////////////////////////
Boolean BrowseFormHandleEvent(EventType * event){

	FormType* frmP = FrmGetActiveForm();
	FormType* form;
	Boolean handled = false;
	Char* p;
	UInt32	x;
	
	frmP = FrmGetActiveForm();
	
	switch (event->eType){
			
		case frmOpenEvent:
			BrowseFormInit(frmP);
			handled = true;
			break;
												
		case ctlSelectEvent:
			switch (event->data.ctlSelect.controlID){
				case BrowseCategoryPopTrigger:
					WordListSelectCategory();
					handled = true;
					break;
							
				case BrowseQuitButton:
					
					//close database if possible
					if (CurrentDB != NULL) {
						if (errNone != DmCloseDatabase(CurrentDB))
						DoCustomDialog("错误", "无法关闭数据库", false, 0, NULL, false);
					}

					FrmGotoForm(MainForm);
					handled = true;
					break;
				
				case BrowseNewButton:
					EditNewRecord();
					handled = true;
					break;

				case BrowseShuffleButton:
					ShuffleStudyList();
					handled = true;
					break;
										
				//case BrowseSortButton:
				//	SortStudyList();					
				//	handled = true;
				//	break;
				
				case BrowseAddAllButton:
					BatchMoveToStudyList();
					handled = true;
					break;
					
				case BrowseRemoveAllButton:
					BatchMoveToRawList();
					handled = true;
					break;
					
				case BrowseStudyListPushButton:
					ChangeTab(StudyListTab);
					break;
				
				case BrowseRawPushButton:
					ChangeTab(RawTab);
					break;
				
				case BrowseAllPushButton:
					ChangeTab(AllTab);
					break;
				
				//case BrowseGoButton:
				//	RandomNewRecord();
				//	break;
					
				default:
					break;
			
			}
			break;
			
		case ctlRepeatEvent:
			switch(event->data.ctlSelect.controlID){
				
				case BrowseScrollUpRepeating:
					WordListBackward(false);
					break;
							
				case BrowseScrollDownRepeating:
					WordListForward(false);
					break;
			}
			break;
			
		case tblSelectEvent:
			TblUnhighlightSelection(event->data.tblSelect.pTable);
			CurrentRecord = TblGetRowID(event->data.tblSelect.pTable, event->data.tblSelect.row);
			
			switch(event->data.tblSelect.column){
				case statusColumn:
					FrmPopupForm(DetailForm);
					break;
					
				case entryColumn:
			
					TopVisibleFieldIndex = 0;
					EditRowIDWhichHadFocus = FirstFieldIndex;
					EditFieldPosition = 0;
			
					FrmGotoForm(EditForm);
					break;
				
				case arrowColumn:
					switch(tabCurrentSelected){
						case StudyListTab:
							MoveToRawList(event->data.tblSelect.row);
							break;
							
						case RawTab:
							MoveToStudyList(event->data.tblSelect.row);
							break;
							
						case AllTab:
							form = FrmInitForm(StatusForm);
							FrmDoDialog(form);
							FrmDeleteForm(form);
							break;
					}
					break;
				}
			handled = true;
			break;
			
		case penDownEvent:
			//capture pen down only if raw tab is displayed
			if (tabCurrentSelected == RawTab){
				DetectPenDown(event);
			}	
			break;
				
		case keyDownEvent:
		
			//if (TxtCharIsHardKey(event->data.keyDown.modifiers, event->data.keyDown.chr))
			//{
			//}

			if (EvtKeydownIsVirtual(event))
			{
				if (event->data.keyDown.chr == pageUpChr){
					//ctl = GetObjectPtr(BrowseScrollUpRepeating);
					//if (CtlGetValue(ctl) != 0)
					WordListBackward(false);
					
					if (!(event->data.keyDown.modifiers & autoRepeatKeyMask)) handled = true;
				}
				
				else if (event->data.keyDown.chr == pageDownChr){
					//ctl = GetObjectPtr(BrowseScrollDownRepeating);
					//if (CtlGetValue(ctl) != 0)
					WordListForward(false);
					
					if (!(event->data.keyDown.modifiers & autoRepeatKeyMask)) handled = true;
				}
			}
		

			else if (event->data.keyDown.chr == linefeedChr)
			{
				handled = true;
			}

			else {
				InstantLookup(event);
				handled = true;
			}
			
		break;
		
		case fldEnterEvent:
			FldHandleEvent(event->data.fldEnter.pField, event);
			
			p = FldGetTextPtr(event->data.fldEnter.pField);
			if ((p != NULL) && (StrLen(p) > 0))
			FldSetSelection(event->data.fldEnter.pField, 0, StrLen(p));
			
			if (tabCurrentSelected == RawTab){
				SearchFieldTicking = true;
				SearchFieldTicks = TimGetTicks();
			}
		
			handled = true;
			break;
		

		case fldChangedEvent:
			InstantLookup(event);
			handled = true;
			break;
		
		case nilEvent:
			x = TimGetTicks();
			if ((tabCurrentSelected == RawTab) &&
				SearchFieldTicking && (( x - SearchFieldTicks) > 500)){
				SearchFieldTicking = false;
				UpdateSearchField();
			}
			break;
			
		default:
			break;
	}
	
	return handled;
}

static void BrowseFormInit( FormType* frmP ){

	Int16 row;
	TableType* tblP;
	ControlPtr ctl;

	if (ShowAllCategories) CurrentCategory = dmAllCategories;
	
	// Initialize the word list table.
	tblP = GetObjectPtr(BrowseWordListTable);

	for (row = 0; row < RowsInTable; row++)
	{
		TblSetItemStyle(tblP, row, statusColumn, customTableItem);
		TblSetItemStyle(tblP, row, entryColumn, customTableItem);
		TblSetItemStyle(tblP, row, arrowColumn, customTableItem);
		TblSetRowUsable(tblP, row, false);
	}

	TblSetColumnUsable(tblP, statusColumn, true);
	TblSetColumnUsable(tblP, entryColumn, true);
	TblSetColumnUsable(tblP, arrowColumn, true);

	TblSetColumnSpacing(tblP, statusColumn, columnSpacing);
	
	// Set the callback routine that will draw the records.
	TblSetCustomDrawProcedure (tblP, statusColumn, WordListDrawRecord);
	TblSetCustomDrawProcedure (tblP, entryColumn, WordListDrawRecord);
	TblSetCustomDrawProcedure (tblP, arrowColumn, WordListDrawRecord);

	// Set the label of the category trigger.
	ctl = GetObjectPtr(BrowseCategoryPopTrigger);
	CategoryGetName (CurrentDB, CurrentCategory, CategoryName);
	CategorySetTriggerLabel (ctl, CategoryName);
	
	ChangeTab(tabCurrentSelected);
}

static void BrowseFormLoadTable( FormType* frmP )
{
	Int16      row = 0;
	TableType* 	tblP;
	UInt16 cursor = 0;
	Boolean full = false;
	Boolean reachedEnd = false;
	Boolean reachedHead = false;
	Int16 i;
	UInt16 studyNums; 
	UInt16 index = 0, recordIndex;
	HeaderItem item;
	Boolean detecting = true;
	UInt32 ticks, ticksPerSecond;
	Err error;

	tblP = GetObjectPtr(BrowseWordListTable);
	
	//	first branch: load study list
	if (tabCurrentSelected == StudyListTab){
				
		//Validation
		studyNums = GetHeaderItemNumber(CurrentDB, LearningRecordIndex);
		
		if (studyNums == 0){
			TopVisibleRecord = 0;
			index = 0;
			row = 0;
		}
		
		else {		
			if (TopVisibleRecord + 10 > studyNums - 1){
				if (studyNums < 11) TopVisibleRecord = 0;
				else TopVisibleRecord = studyNums - 11;
			} 
		
			if (studyNums > RowsInTable) VisibleRows =  RowsInTable;
			else VisibleRows = studyNums;
		
			for (index = TopVisibleRecord; index < TopVisibleRecord + VisibleRows; index ++){
				GetHeaderItem(CurrentDB, LearningRecordIndex, &item, index);
			
				error = DmFindRecordByID(CurrentDB, item, &recordIndex);
				if (error) ErrAlert(error);
			
				TblSetRowID(tblP, row, recordIndex);
				TblSetRowUsable(tblP, row, true);
				row ++;
			}
		}
		
		//	hide empty row
		while(row < RowsInTable){
			TblSetRowUsable(tblP, row, false);
			row ++;
		}
		
		//	draw table
		TblDrawTable(tblP);
		
		//	update search/count field
		UpdateSearchField();
		
		//	update scrollers				
		reachedHead = (TopVisibleRecord == 0);
		reachedEnd = ((TopVisibleRecord + RowsInTable) >= studyNums);
		
		FrmUpdateScrollers(frmP, FrmGetObjectIndex(frmP, BrowseScrollUpRepeating),
			FrmGetObjectIndex(frmP, BrowseScrollDownRepeating), !reachedHead, !reachedEnd);

		return;
	} 
	
	
	ticks = TimGetTicks();
	ticksPerSecond = (UInt32)SysTicksPerSecond();
	
	// 	For each row in the table, store the record number as the row id.
	//	first, check if table full
	if (VisibleRows == RowsInTable) full = true;
	
	//	forward search to fill table
	if (!full){

		if (VisibleRows == 0) cursor = TopVisibleRecord;
		else cursor = TblGetRowID(tblP, VisibleRows - 1) + 1;
		
		while (SeekNextRecord(&cursor, dmSeekForward)){
		
			if (detecting && ((TimGetTicks() - ticks) > ticksPerSecond / 2)){
				FntSetFont(largeBoldFont);
				WinDrawChars("Searching....", 9, 50, 70); 
				detecting = false;
			} 
		
			TblSetRowID(tblP, VisibleRows, cursor);
			TblSetRowUsable(tblP, VisibleRows, true);
		
			VisibleRows ++;
			cursor ++;
		
			if (VisibleRows == RowsInTable){
				full = true;
				break;
			}
		}
	}
	
	//	backward search to fill table	
	if (!full) {
		
		reachedEnd = true;
	
		if (VisibleRows == 0) cursor = TopVisibleRecord - 1;
		else cursor = TblGetRowID(tblP, 0) - 1;
	
		while (SeekNextRecord(&cursor, dmSeekBackward)){
		
			if (detecting && ((TimGetTicks() - ticks) > ticksPerSecond / 2)){
				FntSetFont(largeBoldFont);
				WinDrawChars("Searching....", 9, 50, 70); 
				detecting = false;
			} 

			for (i = VisibleRows; i > 0; i--)
				TblSetRowID(tblP, i, TblGetRowID(tblP, i-1));
				
			TblSetRowID(tblP, 0, cursor);
			TblSetRowUsable(tblP, VisibleRows, true);
						
			VisibleRows ++;
			cursor --;
		
			if (VisibleRows == RowsInTable){
				full = true;
				break;
			}
		}
		
		if (!full) reachedHead = true;
	}
	
	if (VisibleRows == 0){
		reachedHead = true;
		reachedEnd = true;
	}
	
	if (!reachedHead) {
		cursor = TblGetRowID(tblP, 0) - 1;
		reachedHead = !SeekNextRecord(&cursor, dmSeekBackward);
	}
	
	if (!reachedEnd) {
		cursor = TblGetRowID(tblP, VisibleRows - 1) + 1;	
		reachedEnd = !SeekNextRecord(&cursor, dmSeekForward);
	}

	// Hide the item that don't have any data.
	row = VisibleRows;
	while (row < RowsInTable)
	{
		TblSetRowUsable (tblP, row, false);
		row++;
	}
	
	TblDrawTable(tblP);
		
	//update scrollers
	FrmUpdateScrollers(frmP, FrmGetObjectIndex(frmP, BrowseScrollUpRepeating),
		FrmGetObjectIndex(frmP, BrowseScrollDownRepeating), !reachedHead, !reachedEnd);

	//update top visible record
	if (VisibleRows) TopVisibleRecord = TblGetRowID(tblP, 0);

	//	update search field if 
	//	2. raw tab and search field not focused
	if 	((tabCurrentSelected == RawTab) && (!SearchFieldTicking))
		UpdateSearchField();

}

static void	WordListDrawRecord (void * table, Int16 row, Int16 column, RectanglePtr bounds){

	UInt16 recordNum;
	Err error;
	WordRecordType record;
	MemHandle recordH;
	Int16 strWidth = 75;	//75 pixel at most for question field
	Int16 strLength = 0;
	Int16 offset = 0;
	Boolean fitWithinWidth = true;
	char* strP;
	char arrowChar;
	char infoChar;
	HeaderQueue queue;
	
	// Get the record number that corresponds to the table item to draw.
	// The record number is stored in the "intValue" field of the item.
	recordNum = TblGetRowID (table, row);

	error = GetWordRecord (CurrentDB, recordNum, &record, &recordH);
	if (error)
	{
		ErrNonFatalDisplay ("Record not found");
		return;
	}

	switch (column)
	{
		case entryColumn:
			if (record.field[WordFieldQuestion] != NULL) {
				strP = record.field[WordFieldQuestion];
				FntSetFont(boldFont);
				strLength = StrLen(strP);
				FntCharsInWidth(strP, &strWidth, &strLength, &fitWithinWidth);
				
				WinDrawChars(strP, strLength, bounds->topLeft.x, bounds->topLeft.y);
			}
			
			if (record.field[WordFieldAnswer] != NULL){
				strP = record.field[WordFieldAnswer];
				FntSetFont(stdFont);
				strLength = StrLen(strP);
				offset = strWidth + 10;
				strWidth = TblGetColumnWidth(table, entryColumn) - offset;
				FntCharsInWidth(strP, &strWidth, &strLength, &fitWithinWidth);
				
				WinDrawChars(strP, strLength, bounds->topLeft.x + 
					TblGetColumnWidth(table, entryColumn) - strWidth, bounds->topLeft.y);
			}
				
			break;
		case statusColumn:
			FntSetFont(symbolFont);
			infoChar = 10;
			WinDrawChars(&infoChar, 1, bounds->topLeft.x + 2, bounds->topLeft.y);
			FntSetFont(stdFont);
			break;
		
		case arrowColumn:
			
			switch(tabCurrentSelected){
				case StudyListTab:
					arrowChar = 187;
					break;
				case RawTab:
					arrowChar = 171;
					break;
				case AllTab:
					queue = GetQueue(CurrentDB, TblGetRowID(table, row));			
					arrowChar = WordQueueToChar(queue);
					break;
			}

			FntSetFont(boldFont);
			WinDrawChars(&arrowChar, 1, bounds->topLeft.x + 1, bounds->topLeft.y);
			FntSetFont(stdFont);
			
			break;
		
	}

	MemHandleUnlock(recordH);
}

UInt16 WordListSelectCategory (void)
{
	FormType* frmP;
	UInt16 category;
	Boolean categoryEdited;

	// Process the category popup list.
	category = CurrentCategory;

	frmP = FrmGetActiveForm();
	categoryEdited = CategorySelect (CurrentDB, frmP, BrowseCategoryPopTrigger,
			BrowseWordCategoryList, true, &category, CategoryName, 1, categoryDefaultEditCategoryString);

	if (category == dmAllCategories)
		ShowAllCategories = true;
	else
		ShowAllCategories = false;

	if ( categoryEdited || (category != CurrentCategory))
	{
		ToolsChangeCategory (category);

		// Display the new category.
		VisibleRows = 0;
		BrowseFormLoadTable(frmP);

		// By changing the category the current record is lost.
		CurrentRecord = noRecord;
	}

	return (category);
}

⌨️ 快捷键说明

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