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

📄 quiklist.c

📁 CD_高级PALM编程
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************* FILE:					QuikList.c** DESCRIPTION:	The QuikList project module. This version of QuikList shows you*							how to implement a database-based list with multi-character*							Graffiti lookup and category support. The category support*							is for read-only databases.		** VERSION:			3.0**********************************************************************/#include <PalmOS.h>#include <TxtGlue.h>#include "QuikList.h"#include "QuikListRsc.h"#include "Utils.h"#include "UtilsRsc.h"/*********************************************************************** * FUNCTION:    	StartGraffitiLookup * * DESCRIPTION: 	Initiate a record lookup using a user-entered keystroke, *							The lookup uses a two-part timing mechanism: one setting *							for the EvtGetEvent timeout value, and a secondary counter. * * RETURNED:    	Nothing. * * SIDE EFFECT: 	sets three global variables: *							gFindStr (the lookup string), the EvtGetEvent timeout setting, *							and the lookup counter. ***********************************************************************/static	void  StartGraffitiLookup(	Char	chr	// ( in )  The next char to put in the lookup string){	Int32	fStrLen = StrLen ( gFindStr );		// Turn on lookup indicator so user knows a lookup is taking place	FrmShowObject ( 		FrmGetActiveForm (), FrmGetObjectIndex ( 		FrmGetActiveForm (), MainLookupIndicatorLabel ));	// Set up the lookup string	gFindStr [ fStrLen ]        = chr;	gFindStr [ fStrLen + 1 ] = NULL;		// Arm (rearm) the nilEvent timer and its counter. We need a value > 1 in// gNilEventCnt because nilEvents may appear for reasons other than// the timer. 	gEventTimeout	= LOOKUP_TIMER_CNT;	gNilEventCnt 		= NIL_EVENT_CNT;}/*********************************************************************** * FUNCTION:    	StopGrafftiLookup * * DESCRIPTION: 	Check to see if there's an active Graffiti lookup going on. *							If so, check for termination. This gets called every *							LOOKUP_TIMER_CNT ticks until gNilEventCnt is zero. * * RETURNED:    	Nothing.  ***********************************************************************/static void  StopGrafftiLookup(	void){	gNilEventCnt--;	if ( gNilEventCnt == 0 )	{// Hide the lookup indicator,  clear the lookup string, and // turn off nilEvent generation.		FrmHideObject ( FrmGetActiveForm (), 			FrmGetObjectIndex ( 			FrmGetActiveForm (), MainLookupIndicatorLabel ));		gFindStr [ 0 ] = NULL;		gEventTimeout = evtWaitForever;	}}#pragma mark ----------------/*********************************************************************** * FUNCTION:    	DBGetNthRecInCategory * * DESCRIPTION: 	Find the Nth record in a category and return its *							physical record number in database. * * RETURNED:    	The record index or -1 if it can't be found. ***********************************************************************/static Int16  	DBGetNthRecInCategory(	DmOpenRef	dbRef, 			// ( in )  the database to search	UInt16				recNum,		// ( in )  the relative rec # to find	UInt16				curCat,		// ( in )  the current category	UInt16				numRecs	// ( in )  # recs in the current category){	Err			error;	Int16		result = -1;	UInt16		realRecNum;	UInt16		offset;	Int16		direction;	// Some preventative error checking. Should never happen.	if ( recNum < numRecs )	{	// Set up forward search for records in 1st half of category.// Start at 1st record and search forward		if ( recNum < ( numRecs / 2 ))		{			realRecNum 	= 0;			offset  		= recNum;			direction 	= dmSeekForward;		}		else	// Backward search for 1st half of category records.// Start at last record and search backward.		{			realRecNum 	= dmMaxRecordIndex;			offset  			= numRecs - recNum - 1;			direction 		= dmSeekBackward;		}// Look for the record.		error = DmSeekRecordInCategory ( 			dbRef, &realRecNum, offset, direction,  curCat );		if ( error == 0 )			result = ( Int16 ) realRecNum;	}	return ( result );}/*********************************************************************** * FUNCTION:    	DBSearch * * DESCRIPTION: 	Search a database for the first record alphabetically that *							matches a specific string. NOTE: This routine assumes that *							the database records are sorted in ascending order. *					 * RETURNED:    	-1 if no match is found, the record index otherwise. ***********************************************************************/static	Int32	DBSearch( 	Char * 			fStrP,		// ( in )  the string to match against	DmOpenRef	dbRef, 		// ( in )  the database to search	UInt16				curCat		// ( in )  the active category){	Char		recData [ MAX_NAME_LENGTH ];	Int16		compare, result = -1;	Int16		realRecNum;	UInt16 	mid, lower 	= 0;	UInt16		fStrLen 			= ( UInt16 ) StrLen ( fStrP );	UInt16		upper 				= ( UInt16 ) gListSize;	// Binary search thru the database looking for a match		do 	{	// Get the next record number		mid = (( lower + upper ) / 2 );		realRecNum = DBGetNthRecInCategory ( dbRef, mid, curCat, ( UInt16 ) gListSize );		if ( realRecNum >= 0 )		{		// Check for a match					GetRecordData ( dbRef, ( UInt16 ) realRecNum, recData );			compare = 				TxtCaselessCompare ( fStrP, fStrLen, NULL, recData, fStrLen, NULL );// Found, return record # and get out the binary search loop			if ( compare == 0 )			{				result = ( Int16 ) mid;				break;			}		}// Check for termination				if ( mid == lower || mid == upper )			break;		// Not found, move search location				else if ( compare < 0 ) 			upper = mid;				else			lower = mid;				} while ( 1 );// If a match, look at the predecessor records sequentially// to find the lowest record # that still matches.	if ( result > 0 )	{		do		{		// Save current match for return value to avoid an extra record lookup at end of this loop			result--;			realRecNum = DBGetNthRecInCategory ( dbRef, ( UInt16 ) result, curCat, ( UInt16 ) gListSize );			if ( realRecNum >= 0 )			{			// Compare the previous logical record against the lookup string				GetRecordData ( dbRef, ( UInt16 ) realRecNum, recData );				compare = 					TxtCaselessCompare ( fStrP, fStrLen, NULL, recData, fStrLen, NULL );			// When we hit the first record that doesn't match, set the return value// to the lowest physical record # that does match and exit.				if ( compare > 0 )				{					result++;					break;				}			}		} while ( result != 0 );	}				return ( result );}#pragma mark ----------------/*********************************************************************** * FUNCTION:    	MainFormDrawList ** DESCRIPTION:	Draw the main form list. In between each line,* 							check for a new incoming keystroke. If there is one, do* 							another Graffiti lookup.  * * RETURNED:    	nothing ***********************************************************************/static void MainFormDrawList(	void){#define	NUM_REDRAWS	10	UInt16			i, j;	Coord			x, y;	EventType 	event;	Char			name [ MAX_NAME_LENGTH ];	Int16			result;// Erase the list's rectangle	WinEraseRectangle ( &gListBounds, 0 );	for ( i = 0; i < VIS_ITEMS; i++ )	{	// Check for keystroke in middle of list redraw.// If there is one, do a lookup to see if there is a new list location// match. If so, stop redrawing until the next redraw kicks in.// StopRedraw is set in ProcessKeystroke. 		if ( ! gStopDrawing )		{			if ( EvtSysEventAvail ( false ))			{				EvtGetEvent ( &event, 0 );				SysHandleEvent ( &event );				if ( event.eType == keyDownEvent )				{					Boolean handled = MainFormProcessKeystroke (						( UInt8 ) event.data.keyDown.chr, true );					if ( gStopDrawing ) return;			}	}// No event available, get the correct record			*name = NULL;			result = ( Int16 ) DBGetNthRecInCategory ( gDBRef, ( UInt16 ) ( gTopItem + i ), gCurCatNum, ( UInt16 ) gListSize );			if ( result >= 0 )			{				GetRecordData ( gDBRef, ( UInt16 ) result, name );// Draw the current line				x = ( Coord ) ( gListBounds.topLeft.x + 2 );				y = ( Coord ) ( gListBounds.topLeft.y + ( i * FONT_HEIGHT ));				for ( j = 0; j < NUM_REDRAWS; j++ )					WinDrawChars ( name, StrLen ( name ), x, y );			}		}	}}/*********************************************************************** * FUNCTION:    	FitToListBoundaries * * DESCRIPTION: 	Check an incoming list position to make sure it* 							it fits within the legal boundaries for the list. * * RETURNED:    	A valid list position ***********************************************************************/static Int16 FitToListBoundaries(	Int16		topItem		// ( in )  the list item to check){	Int16		result = topItem;		if ( result < 0 )		result = 0;	if ( result > gListSize - VIS_ITEMS )		result = gListSize - VIS_ITEMS;	return ( result );}/*********************************************************************** * FUNCTION:    	MainFormProcessKeystroke * * DESCRIPTION: 	Process a keystroke event for the Main form. Two types *							of events are handled--hardware scroll up and down buttons *							and Graffiti-based record lookup. * * RETURNED:    	True if the keystroke is handled. ***********************************************************************/static Boolean MainFormProcessKeystroke(	UInt8			chr,				// ( in )  Keystroke to process	Boolean		drawing		// ( in )  Currently drawing a list?){	Boolean		handled	= false;	ListPtr	 		listP 		= GetObjectPtr ( MainNamesList );	if ( listP ==  NULL ) return handled;// First, check for scroll up/down buttons		if ( chr == vchrPageUp )	{		if ( gTopItem != 0 )		{			gTopItem = FitToListBoundaries ( gTopItem - VIS_ITEMS + 1 );			MainFormDrawList ();		}		handled = true;	}	else	if ( chr == vchrPageDown )	{		if ( gTopItem != gListSize - VIS_ITEMS )		{			gTopItem = FitToListBoundaries ( gTopItem + VIS_ITEMS - 1 );			MainFormDrawList ();		}		handled = true;	}	else // If it's a valid char, start Graffiti lookup	//	if ( TxtGlueCharIsAlNum ( chr ) && DmNumRecordsInCategory ( gDBRef, gCurCatNum ) > 0 )	if ( TxtGlueCharIsPrint ( chr ) && gListSize > 0 )	{		Int32 recLoc 	= -1;		handled 			= true;// Only do the lookup if there's room in the lookup string				if ( StrLen ( gFindStr ) < MAX_MATCH_CHAR )		{			StartGraffitiLookup (( Char ) chr );		// Lookup started, check for a record that starts with the string						recLoc = DBSearch ( gFindStr, gDBRef, gCurCatNum );			if ( recLoc >= 0 )			{		// Found a record, redraw the list so the matched record is the topmost// visible item. If this is a draw for a new multi-char match (if drawing is true),// this redraw takes place before the previous list drawing completes.				gTopItem = FitToListBoundaries (( Int16 ) recLoc );				MainFormDrawList ();					// Disable drawing the previous list if one is in progress. If not, enable drawing// in case this is the 1st list drawing of a multi-char match that previously// disable redrawing.				gStopDrawing = drawing;			}		}	}	return ( handled );}#pragma mark ----------------/*********************************************************************** * FUNCTION:    	MainFormHandleRWCategory * * DESCRIPTION: 	Handle a category popup event for a Read/Write database. * * RETURNED:    	nothing * ***********************************************************************/static void MainFormHandleRWCategory

⌨️ 快捷键说明

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