contacts.c

来自「CD_《Palm OS编程实践》」· C语言 代码 · 共 1,566 行 · 第 1/3 页

C
1,566
字号
  		// CH.3 Get the index of our field
		index = FrmGetObjectIndex( form, ContactDetailFirstNameField );

		// CH.3 Set the focus to the First Name field
		FrmSetFocus( form, index );
		
		// CH.5 Set upper shift on
		GrfSetState( false, false, true );			
	}
	
	// CH.5 We're done
	return;
}

// CH.5 Puts any field changes in the record
static void getFields( void )
{
	FormPtr		form;		// CH.5 The contact detail form
	
	// CH.5 Get the contact detail form pointer
	form = FrmGetActiveForm();
		
	// CH.5 Turn off focus
	FrmSetFocus( form, -1 );
			
	// CH.5 If the record has been modified
	if( isDirty )
	{
		CharPtr	precord;	// CH.5 Points to the DB record
	
		// CH.7 Detach the record from the database
		DmDetachRecord( contactsDB, cursor, &hrecord );
		
		// CH.5 Lock the record
		precord = MemHandleLock( hrecord );
		
		// CH.5 Get the text for the First Name field
		getText( getObject( form, ContactDetailFirstNameField ),
				precord, DB_FIRST_NAME_START );
		
		// CH.5 Get the text for the Last Name field
		getText( getObject( form, ContactDetailLastNameField ),
				precord, DB_LAST_NAME_START );
		
		// CH.5 Get the text for the Phone Number field
		getText( getObject( form, ContactDetailPhoneNumberField ),
				precord, DB_PHONE_NUMBER_START );
		
		// CH.7 Find the proper position
		cursor = DmFindSortPosition( contactsDB, precord, NULL,
				(DmComparF*)sortFunc, sortBy );
		
		// CH.5 Unlock the record
		MemHandleUnlock( hrecord );
		
		// CH.7 Reattach the record
		DmAttachRecord( contactsDB, &cursor, hrecord, NULL );
	}

	// CH.5 Reset the dirty bit
	isDirty = false;
				
	// CH.5 We're done
	return;
}

// CH.5 Set the text in a field
static void setText( FieldPtr field, CharPtr text )
{
	VoidHand	hfield;	// CH.5 Handle of field text
	CharPtr		pfield;	// CH.5 Pointer to field text
	
	// CH.5 Get the current field handle
	hfield = FldGetTextHandle( field );
	
	// CH.5 If we have a handle
	if( hfield != NULL )
	{
		// CH.5 Resize it
		if( MemHandleResize( hfield, StrLen( text ) + 1 ) != 0 )
			errorExit( MemoryErrorAlert );
	}
	
	else
	// CH.5 Allocate a handle for the string
	{
		hfield = MemHandleNew( StrLen( text ) + 1 );
		if( hfield == NULL )
			errorExit( MemoryErrorAlert );
	}
	
	// CH.5 Lock it
	pfield = MemHandleLock( hfield );
	
	// CH.5 Copy the string
	StrCopy( pfield, text );
	
	// CH.5 Unlock it
	MemHandleUnlock( hfield );
	
	// CH.5 Give it to the field
	FldSetTextHandle( field, hfield );
	
	// CH.5 Draw the field
	FldDrawField( field );
	
	// CH.5 We're done
	return;
}	

// CH.5 Get the text from a field
static void getText( FieldPtr field, VoidPtr precord, Word offset )
{
	CharPtr		pfield;	// CH.5 Pointer to field text

	// CH.5 Get the text pointer
	pfield = FldGetTextPtr( field );
	
	// CH.5 Copy it
	DmWrite( precord, offset, pfield, StrLen( pfield ) );
	
	// CH.5 We're done
	return;
}

// CH.6 Set the Contact Detail date selector trigger
static void setDateTrigger( void )
{
	FormPtr		form;		// CH.5 The contact detail form
	
	// CH.6 Get the contact detail form pointer
	form = FrmGetActiveForm();
	
	// CH.6 If there is no date
	if( dateTime.year == NO_DATE )
	{
		CtlSetLabel( getObject( form, ContactDetailDateSelTrigger ),
				"          " );
	}
	
	else
	// CH.6 If there is a date
	{
		Char dateString[dateStringLength];
		
		// CH.6 Get the date string
		DateToAscii( dateTime.month, dateTime.day, dateTime.year,
				(DateFormatType)PrefGetPreference( prefDateFormat ), dateString );
		
		// CH.6 Set the selector trigger label
		CtlSetLabel( getObject( form, ContactDetailDateSelTrigger ),
				dateString );
				
	}
	
	// CH.6 We're done
	return;
}

// CH.6 Set the Contact Detail time selector trigger
static void setTimeTrigger( void )
{
	FormPtr		form;		// CH.5 The contact detail form
	
	// CH.6 Get the contact detail form pointer
	form = FrmGetActiveForm();
	
	// CH.6 If there's no time
	if( dateTime.hour == NO_TIME )
	{
		CtlSetLabel( getObject( form, ContactDetailTimeSelTrigger ),
				"          " );
	}
	
	else
	// CH.6 If there is a time
	{
		Char timeString[timeStringLength];
		
		// CH.6 Get the time string
		TimeToAscii( dateTime.hour, dateTime.minute,
				(TimeFormatType)PrefGetPreference( prefTimeFormat ), timeString );
		
		// CH.6 Set the selector trigger label
		CtlSetLabel( getObject( form, ContactDetailTimeSelTrigger ),
				timeString );
				
	}

	// CH.6 We're done
	return;
}

// CH.6 Set the controls in the Enter Time form based on dateTime
static void setTimeControls( void )
{
	FormPtr		form;
	ControlPtr	hourButton;
	ControlPtr	minuteTensButton;
	ControlPtr	minuteOnesButton;
	ControlPtr	amButton;
	ControlPtr	pmButton;
	ControlPtr	noTimeCheckbox;
	Char		labelString[3];
	SWord		hour;
	
	// CH.6 Get the form
	form = FrmGetActiveForm();
	
	// CH.6 Get the control pointers
	hourButton = getObject( form, EnterTimeHoursPushButton );
	minuteTensButton = getObject( form,
			EnterTimeMinuteTensPushButton );
	minuteOnesButton = getObject( form,
			EnterTimeMinuteOnesPushButton );
	amButton = getObject( form, EnterTimeAMPushButton );
	pmButton = getObject( form, EnterTimePMPushButton );
	noTimeCheckbox = getObject( form, EnterTimeNoTimeCheckbox );
	
	// CH.6 If there is a time
	if( dateTime.hour != NO_TIME )
	{
		// CH.6 Update the hour
		hour = dateTime.hour % 12;
		if( hour == 0 )
			hour = 12;
		CtlSetLabel( hourButton,
				StrIToA( labelString, hour ) );

		// CH.6 Update the minute tens
		CtlSetLabel( minuteTensButton,
				StrIToA( labelString, dateTime.minute / 10 ) );
	
		// CH.6 Update the minute ones
		CtlSetLabel( minuteOnesButton,
				StrIToA( labelString, dateTime.minute % 10 ) );
	
		// CH.6 Update AM
		CtlSetValue( amButton, (dateTime.hour < 12) );
				
		// CH.6 Update PM
		CtlSetValue( pmButton, (dateTime.hour > 11) );

		// CH.6 Uncheck the no time checkbox
		CtlSetValue( noTimeCheckbox, false );
	}
	
	else
	// If there is no time
	{
		// CH.6 Update the hour
		CtlSetValue( hourButton, false );
		CtlSetLabel( hourButton, "" );
		
		// CH.6 Update the minute tens
		CtlSetValue( minuteTensButton, false );
		CtlSetLabel( minuteTensButton, "" );
		
		// CH.6 Update the minute ones
		CtlSetValue( minuteOnesButton, false );
		CtlSetLabel( minuteOnesButton, "" );
		
		// CH.6 Update AM
		CtlSetValue( amButton, false );
				
		// CH.6 Update PM
		CtlSetValue( pmButton, false );

		// CH.6 Uncheck the no time checkbox
		CtlSetValue( noTimeCheckbox, true );
	}
	
	// CH.6 We're done
	return;
}

// CH.7 This function is called by Palm OS to sort records
static Int sortFunc( CharPtr precord1, CharPtr precord2, Int sortBy )
{
	Int sortResult;
	
	// CH.7 Switch based on sort criteria
	switch( sortBy )
	{
		// CH.7 Sort by date and time
		case SORTBY_DATE_TIME:
		{
			DateTimePtr pdateTime1;
			DateTimePtr pdateTime2;
			Long lDiff;
			
			pdateTime1 = (DateTimePtr)(precord1 + DB_DATE_TIME_START);
			pdateTime2 = (DateTimePtr)(precord2 + DB_DATE_TIME_START);
			
			// CH.7 Compare the dates and times
			lDiff = (Long)(TimDateTimeToSeconds( pdateTime1 ) / 60 ) -
					(Long)(TimDateTimeToSeconds( pdateTime2 ) / 60 );
			
			// CH.7 Date/time #1 is later
			if( lDiff > 0 )
				sortResult = 1;
			
			else	
			// CH.7 Date/time #2 is later
			if( lDiff < 0 )
				sortResult = -1;
				
			else
			// CH.7 They are equal
				sortResult = 0;
		}
		break;		

		// CH.7 Sort by first name
		case SORTBY_FIRST_NAME:
		{
			sortResult = StrCompare( precord1 + DB_FIRST_NAME_START,
					precord2 + DB_FIRST_NAME_START );
		}
		break;
		
		// CH.7 Sort by last name
		case SORTBY_LAST_NAME:
		{
			sortResult = StrCompare( precord1 + DB_LAST_NAME_START,
					precord2 + DB_LAST_NAME_START );
		}
		break;		
	}
	
	// CH.7 We're done
	return( sortResult );
}

// CH.8 Draw our list of choices using a table object
static void drawTable( void )
{
	FormPtr		form;
	TablePtr	table;
	Int			column;
	Int			count;
	ControlPtr	upArrow;
	ControlPtr	downArrow;
	
	// CH.8 Get the form pointer
	form = FrmGetActiveForm();
	
	// CH.8 Get the table pointer
	table = getObject( form, ContactListTableTable );
	
	// CH.8 For all columns
	for( column = 0; column < TABLE_NUM_COLUMNS; column++ )
	{
		// CH.8 Set the draw routine
		TblSetCustomDrawProcedure( table, column, drawCell );
		
		// CH.8 Make the column visible
		TblSetColumnUsable( table, column, true );
	}
	
	// CH.8 Initialize the table styles
	for( count = 0; count < TABLE_NUM_ROWS; count++ )
	{
		// CH.8 If there is data
		if( count < numRecords )
		{
			// CH.8 Show the row
			TblSetRowUsable( table, count, true );
		
			// CH.8 Set the cell styles	
			for( column = 0; column < TABLE_NUM_COLUMNS; column++ )
				TblSetItemStyle( table, count, column, customTableItem );
		}
		
		else
		// CH.8 Hide unused rows if any
			TblSetRowUsable( table, count, false );
	}
		
	// CH.8 Draw the table
	TblDrawTable( table );

	// CH.8 Get pointers to the arrow buttons
	upArrow = getObject( form, ContactListRecordUpRepeating );
	downArrow = getObject( form, ContactListRecordDownRepeating );

	// CH.8 Update the arrow buttons and scrollbars
	if( numRecords > TABLE_NUM_ROWS )
	{
		// CH.8 Show the up arrow
		if( cursor > 0 )
		{
			CtlSetLabel( upArrow, BLACK_UP_ARROW );
			CtlSetEnabled( upArrow, true );
		}
		else
		{
			CtlSetLabel( upArrow, GRAY_UP_ARROW );
			CtlSetEnabled( upArrow, false );
		}
		CtlShowControl( upArrow );
		
		// CH.8 Show the down arrow
		if( cursor >= numRecords - TABLE_NUM_ROWS )
		{
			CtlSetLabel( downArrow, GRAY_DOWN_ARROW );
			CtlSetEnabled( downArrow, false );
		}
		else
		{
			CtlSetLabel( downArrow, BLACK_DOWN_ARROW );
			CtlSetEnabled( downArrow, true );
		}
		CtlShowControl( downArrow );
		
		// CH.8 Show the scrollbar
		FrmShowObject( form, FrmGetObjectIndex( form,
				ContactListScrollbarScrollBar ) );
		SclSetScrollBar( getObject( form,
				ContactListScrollbarScrollBar ), cursor, 0,
				numRecords - TABLE_NUM_ROWS, TABLE_NUM_ROWS );
	}
	else
	{
		// CH.8 Hide the arrows
		CtlHideControl( upArrow );
		CtlHideControl( downArrow );
		
		// CH.8 Hide the scrollbar
		FrmHideObject( form, FrmGetObjectIndex( form,
				ContactListScrollbarScrollBar ) );
	}
	
	// CH.8 We're done
	return;
}

// CH.8 The custom drawing routine for a table cell
static void drawCell( VoidPtr table, Word row, Word column,
		RectanglePtr bounds )
{
	Int		record;
	CharPtr	precord;
	Char	string[DB_FIRST_NAME_SIZE + DB_LAST_NAME_SIZE];
	SWord	width;
	SWord	len;
	Boolean	noFit;
	
	// CH.8 Calculate our record
	record = cursor + row;

	// CH.8 Get our record
	hrecord = DmQueryRecord( contactsDB, record );
	precord = MemHandleLock( hrecord );

	// CH.8 Get the date and time
	MemMove( &dateTime, precord + DB_DATE_TIME_START,
			sizeof( dateTime ) );
		
	// CH.8 Switch on the column
	switch( column )
	{
		// CH.8 Handle dates
		case TABLE_COLUMN_DATE:
		{
			if( dateTime.year != NO_DATE )
			{
				DateToAscii( dateTime.month, dateTime.day,
						dateTime.year,
						(DateFormatType)PrefGetPreference(
						prefDateFormat ), string );
			}
			else
				StrCopy( string, "-" );
		}
		break;

		// CH.8 Handle times
		case TABLE_COLUMN_TIME:
		{
			if( dateTime.hour != NO_TIME )
			{
				TimeToAscii( dateTime.hour, dateTime.minute,
						(TimeFormatType)PrefGetPreference(
						prefTimeFormat ), string );
			}
			else
				StrCopy( string, "-" );
		}
		break;

		// CH.8 Handle names
		case TABLE_COLUMN_NAME:
		{
			StrCopy( string, precord + DB_FIRST_NAME_START );
			StrCat( string, " " );
			StrCat( string, precord + DB_LAST_NAME_START );
		}
		break;
	}

	// CH.8 Unlock the record
	MemHandleUnlock( hrecord );

	// CH.8 Set the text mode
	WinSetUnderlineMode( noUnderline );
	FntSetFont( stdFont );
	
	// CH.8 Truncate the string if necessary
	width = bounds->extent.x;
	len = StrLen( string );
	noFit = false;
	FntCharsInWidth( string, &width, &len, &noFit );
	
	// CH.8 Draw the cell
	WinEraseRectangle( bounds, 0 );
	WinDrawChars( string, len, bounds->topLeft.x, bounds->topLeft.y );
	
	// CH.8 We're done
	return;
}

⌨️ 快捷键说明

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