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

📄 addrdiallist.c

📁 我的Palm OS 5 SDK zhCN_PIMApps代码。 使用codewarrior 开发环境
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
 *
 * Copyright (c) 1995-2003 PalmSource, Inc. All rights reserved.
 *
 * File: AddrDialList.c
 *
 * Release: Palm OS 5 SDK (68K) R3.
 *
 * Description:
 *  This is the Address Book application's dial list form module.
 *
 *****************************************************************************/

#include <Chars.h>
#include <ErrorMgr.h>
#include <NotifyMgr.h>
#include <StringMgr.h>
#include <SysUtils.h>
#include <TraceMgr.h>
#include <UIResources.h>
#include <DataMgr.h>
#include <LocaleMgr.h>
#include <Form.h>
#include <Helper.h>
#include <HelperServiceClass.h>
#include <TextMgr.h>
#include <PalmLocale.h>
#include <PalmUtils.h>

#include "AddrDialList.h"
#include "Address.h"
#include "AddrTools.h"
#include "AddressRsc.h"
#include "AddressDB.h"
#include "AddrDefines.h"


#define kSpaceBetweenLabelAndNumber 6
#define kLeftAndRightSpace			2
#define	kMaxPhonesCount				25
#define kMaxCharsPhoneNumber		25

// Convenient access
#define gAddrP			(&(gDialListData->addr))
#define gAddrH			(gDialListData->addrH)
#define gAppInfoP		(gDialListData->appInfoP)
#define gDisplayName	(gDialListData->displayName)
#define gPhones			(gDialListData->phones)
#define gPhonesCount	(gDialListData->phonesCount)
#define gPhoneX			(gDialListData->phoneX)
#define gSelectedIndex	(gDialListData->selectedIndex)


/***********************************************************************
 *
 *	Internal types
 *
 ***********************************************************************/

typedef struct DialListPhoneTag
{
	Char*		label;
	Char*		number;
	Int16		numberLen;
} DialListPhoneType;

typedef struct DialListDataTag
{
	// Input state variables.
	UInt16				recordIndex;
	UInt16				phoneIndex;
	UInt16				lineIndex;
	
	// Record
	MemHandle 			addrH;

	// Temp only accurate when drawing
	AddrDBRecordType	addr;
	AddrAppInfoType*	appInfoP;

	// Record description - allocated
	Char*				displayName;

	// Phone position - got from field position so that localization
	// can enable various position
	// Label will be aligned right + delta to that
	Coord				phoneX;
	Coord				phoneY;
	// X min is got from te Description label
	Coord				displayXMin;
	Coord				displayNameY;

	// list info
	Int16				topIndex;
	Int16				selectedIndex;

	// Array of data
	DialListPhoneType	phones[kMaxPhonesCount];
	UInt16				phonesCount;
} DialListDataType;


/***********************************************************************
 *
 *   Global variables
 *
 ***********************************************************************/

static DialListDataType* gDialListData;
static const Char gPhoneChars[] = "0123456789,+#*";


/***********************************************************************
 *
 *	Internal Functions
 *
 ***********************************************************************/

// Internal tools
static Boolean	PrvDialListCanBePhoneNumber( Char* text, Int16 textLen );
static void		PrvDialListPhoneNumberFilter( Char* outString, Int16* outLen, const Char* inString, Int16 inLen );
static Char*	PrvDialListAllocStringFrom( const Char* s1, const Char* s2, const Char* s3, Boolean checkLineFeed );
static void		PrvDialListSetFieldHandle( FieldType* fldP, MemHandle handle );

// Internal Dial List function
static void		PrvDialListBuildDescription( void );
#ifdef FORM_GADGET_TYPE_IN_CALLBACK_DEFINED // Added for Compatibility with SDK 4.0 update 1
static Boolean	PrvDialListHandleDescriptionEvent( struct FormGadgetTypeInCallback *gadgetP, UInt16 cmd, void *paramP );
#else
static Boolean	PrvDialListHandleDescriptionEvent( struct FormGadgetType *gadgetP, UInt16 cmd, void *paramP );
#endif

static void		PrvDialListInit( FormType* frmP );
static void		PrvDialListInitData( void );
static void		PrvDialListScroll( WinDirectionType direction );
static void		PrvDialListDrawPhoneItem( Int16 index, RectangleType *boundsP, Char **itemsText );
static void		PrvDialListUpdateAfterSelection( FormType* frmP );
static void		PrvDialListUpdatePhoneNumber( FieldType* fldP );
static void		PrvDialListFreeMemory( void );
static void		PrvDialListLeaveDialog( void );
static Boolean	PrvDialListDialSelected( FormType* frmP );


/***********************************************************************
 *
 * FUNCTION:
 *	DialListShowDialog
 *
 * DESCRIPTION:
 *	This routine show the dialog of the given record
 *	if the phoneIndex is not a phone number, first phone number is selected
 *
 * PARAMETERS:
 *	recordIndex		IN		index of the record
 *	phoneIndex		IN		index of the phone, kDialListShowInListPhoneIndex
 *							to use default show in list
 *	lineIndex		IN		index of the line
 *
 * RETURNED:
 *	false if the form must not be displayed
 *
 * REVISION HISTORY:
 *	Name		Date		Description
 *	----		----		-----------
 *	aro			6/12/00		Initial Revision
 *
 ***********************************************************************/
Boolean DialListShowDialog( UInt16 recordIndex, UInt16 phoneIndex, UInt16 lineIndex )
{

	gDialListData = MemPtrNew(sizeof(DialListDataType));
	if (!gDialListData)
		return false;
	MemSet(gDialListData, sizeof(DialListDataType), 0);

	// TraceInit();
	TraceOutput(TL(appErrorClass, "DialListShowDialog() - recordIndex = %hu, phoneIndex = %hu, lineIndex = %hu", recordIndex, phoneIndex, lineIndex));

	// Set up the input vars so that PrvDialListInitData can use them.
	gDialListData->recordIndex = recordIndex;
	gDialListData->phoneIndex = phoneIndex;
	gDialListData->lineIndex = lineIndex;
	
	// Fix for bug 48102.
	// If there is an uncommitted inline session, then the auto-confirm gets processed after the record has been locked
	// During the the next event processing the record is freed  (in PrvEditAutoYomi) ; so we solve this by just setting 
	// things up here and freeing the record after that.  At fromOpenEvent time we again call the routine PrvDialListInitData
	// in order to set the data up.
	PrvDialListInitData();
	
	// Exit if no phone are available for this record
	if (!(gPhonesCount))
		goto exit;
	
	// Unlock the record - we will be re-locking this at frmOpen event.
	if (gAppInfoP)
		MemPtrUnlock(gAppInfoP);
	if (gAddrH)
		MemHandleUnlock(gAddrH);

	// Ok so no show the dialog...
	FrmPopupForm(DialListDialog);

	return true;

exit:
	TraceOutput(TL(appErrorClass, "DialListShowDialog() - exit"));
	PrvDialListFreeMemory();
	return false;
}


/***********************************************************************
 *
 * FUNCTION:    DialListHandleEvent
 *
 * DESCRIPTION: This routine is the event handler for the "Dial List"
 *              of the Address Book application.
 *
 * PARAMETERS:  evtP  - a pointer to an EventType structure
 *
 * RETURNED:    true if the event was handled and should not be passed
 *              to a higher level handler.
 *
 * REVISION HISTORY:
 *			Name		Date		Description
 *			----		----		-----------
 *			aro			6/12/00		Initial Revision
 *
 ***********************************************************************/
Boolean DialListHandleEvent( EventType * evtP )
{
	FormType* frmP;
	Boolean handled = false;

	switch (evtP->eType)
	{
	case lstSelectEvent:
		{
			// Update phone type & number
			// Set focus to the field
			gSelectedIndex = evtP->data.lstSelect.selection;
			frmP = FrmGetActiveForm();
			PrvDialListUpdateAfterSelection(frmP);
			handled = true;
			break;
		}
	case ctlSelectEvent:
		{
			switch (evtP->data.ctlSelect.controlID)
			{
			case DialListDialButton:
				if (PrvDialListDialSelected(FrmGetActiveForm()))
					PrvDialListLeaveDialog();
				handled = true;
				break;
			case DialListCancelButton:
				PrvDialListLeaveDialog();
				handled = true;
				break;
			}
			break;
		}
	case frmOpenEvent:
		{
			frmP = FrmGetActiveForm();
			PrvDialListInitData();
			PrvDialListInit(frmP);
			FrmDrawForm(frmP);
			LstSetSelection(ToolsGetFrmObjectPtr(frmP, DialListList), gSelectedIndex);
			handled = true;
			break;
		}
	case frmCloseEvent:
		{
			TraceOutput(TL(appErrorClass, "Closing form"));
			PrvDialListSetFieldHandle(ToolsGetObjectPtr(DialListNumberField), 0);
			PrvDialListFreeMemory();
			// TraceClose();
			break;
		}
	case keyDownEvent:
		{
			if (TxtCharIsHardKey(evtP->data.keyDown.modifiers, evtP->data.keyDown.chr))
			{
				PrvDialListLeaveDialog();
				handled = true;
			}
			else if (EvtKeydownIsVirtual(evtP))
			{
				// up and down scroll bar without updating the selection
				// Scroll up key presed?
				if (evtP->data.keyDown.chr == vchrPageUp)
				{
					PrvDialListScroll(winUp);
				}
				// Scroll down key presed?
				else if (evtP->data.keyDown.chr == vchrPageDown)
				{
					PrvDialListScroll(winDown);
				}
			}

			break;
		}
	}


	return (handled);
}

#pragma mark -

/***********************************************************************
 *
 * FUNCTION:
 *	PrvDialListCanBePhoneNumber
 *
 * DESCRIPTION:
 *	This routine check if a text could be a phone number
 *	ie if it contains phone chars
 *
 * PARAMETERS:
 *	text	IN	text string to parse
 *	textLen	IN	text len
 *
 * RETURNED:
 *	true if acceptable
 *
 * REVISION HISTORY:
 *	Name		Date		Description
 *	----		----		-----------
 *	aro			6/12/00		Initial Revision
 *	kwk			07/26/00	Modified to use Text Mgr, avoid sign extension
 *							problem calling StrChr with signed Char value.
 *
 ***********************************************************************/
Boolean PrvDialListCanBePhoneNumber( Char* text, Int16 textLen )
{
	UInt16 offset = 0;

	while (offset < textLen)
	{
		WChar curChar;
		offset += TxtGetNextChar(text, offset, &curChar);
		if ( StrChr(gPhoneChars, curChar) != NULL )
			return true;
	}

	return false;
}


/***********************************************************************
 *
 * FUNCTION:
 *	PrvDialListPhoneNumberFilter
 *
 * DESCRIPTION:
 *	This routine filter a phone number
 *
 * PARAMETERS:
 *	outString	OUT	filterd phone number
 *	outLen		IN	max text len for outString
 *			 	OUT	phone number len
 *	inString	IN	text to filter
 *	inLen		IN	text len
 *
 * RETURNED:
 *	nothing
 *
 * REVISION HISTORY:
 *	Name		Date		Description
 *	----		----		-----------
 *	aro			06/12/00	Initial Revision
 *	fpa			11/11/00	Fixed a coherency problem with SMS: now, +++123+++456 -> + 123 456
 *
 ***********************************************************************/
void PrvDialListPhoneNumberFilter( Char* outString, Int16* outLen, const Char* inString, Int16 inLen )
{
	UInt16 inOffset;
	UInt16 outOffset;
	Boolean fLastWasSpace;

	inOffset = 0;
	outOffset = 0;
	fLastWasSpace = false;

	while ( (inOffset < inLen) && (outOffset < *outLen) )
	{
		WChar curChar;

		inOffset += TxtGetNextChar(inString, inOffset, &curChar);
		if (StrChr(gPhoneChars, curChar))
		{
			// Only + at the beginning
			if ( (curChar == chrPlusSign) && (outOffset > 0) )
			{
				outOffset += TxtSetNextChar(outString, outOffset, chrSpace);
				fLastWasSpace = true;
			}
			else
			{
				outOffset += TxtSetNextChar(outString, outOffset, curChar);
				fLastWasSpace = false;
			}
		}
		else if ( !fLastWasSpace && (outOffset > 0) )	// No space at the beginning
		{
			outOffset += TxtSetNextChar(outString, outOffset, chrSpace);
			fLastWasSpace = true;
		}
	}

	// No space at the end
	if (fLastWasSpace)
		outOffset--;

	TxtSetNextChar(outString, outOffset, chrNull);

	*outLen = outOffset;
}


/***********************************************************************
 *
 * FUNCTION:
 *		PrvDialListAllocStringFrom
 *
 * DESCRIPTION:
 *		This routine build a string from 3 string
 *		It cut after the first lineFeed according to checkLineFeed
 *
 * PARAMETERS:
 *  	s1, s2, s3		IN 	the 3 string that can be null...
 *      checkLineFeed	IN  check lineFeed?
 *
 * RETURNED:
 *		pointer to the string allocated
 *
 * REVISION HISTORY:
 *		Name		Date		Description
 *		----		----		-----------
 *		aro			6/12/00		Initial Revision
 *
 ***********************************************************************/
Char* PrvDialListAllocStringFrom( const Char* s1, const Char* s2, const Char* s3, Boolean checkLineFeed )
{

#define SafeStrLen(string) ( (Int16) ( (string)? StrLen(string) : 0 ) )
#define CopyString(base, string, length) \
	{ if (length) { MemMove(base, string, length + 1); base += length; } } while (false)

	Int16 size = 1;
	Int16 length1;
	Int16 length2;
	Int16 length3;
	Char* string;
	Char* tmpStr;

	// Concatenate all non null & non empty string
	// Cut it at first lineFeed

	length1 = SafeStrLen(s1);
	length2 = SafeStrLen(s2);
	length3 = SafeStrLen(s3);

	size = length1 + length2 + length3 + 1;
	if (size == 1)
		return 0;

	string = MemPtrNew(size);
	if (!string)
		return 0;

	tmpStr = string;
	CopyString(tmpStr, s1, length1);
	CopyString(tmpStr, s2, length2);
	CopyString(tmpStr, s3, length3);

	if (checkLineFeed)
	{
		tmpStr = StrChr(string, chrLineFeed);
		if (tmpStr)
		{
			length1 = tmpStr - string;
			string[length1] = chrNull;
			// Shrink so it can't fail
			MemPtrResize(string, length1 + 1);
		}
	}

	return string;
}


/***********************************************************************
 *
 * FUNCTION:
 *	Safe set field handle, previous one is freed if needed
 *
 * DESCRIPTION:
 *	Safe set field handle, previous one is freed if needed
 *
 * PARAMETERS:
 *	fldP	IN	field
 *	handle	IN	handle
 *
 * RETURNED:
 *	nothing
 *
 * REVISION HISTORY:
 *	Name		Date		Description
 *	----		----		-----------
 *	aro			8/3/00		Initial Revision
 *
 ***********************************************************************/
void	PrvDialListSetFieldHandle( FieldType* fldP, MemHandle handle )
{
	MemHandle oldH;
	oldH = FldGetTextHandle(fldP);
	FldSetTextHandle(fldP, handle);
	if (oldH)
	{
		MemHandleFree(oldH);
	}
}


/***********************************************************************
 *
 * FUNCTION:
 *	PrvDialListBuildDescription
 *
 * DESCRIPTION:
 *	This routine build the description
 *
 * PARAMETERS:
 *	none
 *
 * RETURNED:
 *	nothing
 *
 * REVISION HISTORY:
 *	Name		Date		Description
 *	----		----		-----------
 *	aro			6/12/00		Initial Revision
 *
 ***********************************************************************/
void PrvDialListBuildDescription( void )
{
	NameLayoutFieldMapType	nameLayoutFMap;
	Char					separatorStr[kMaxSeparatorStrLen];
	
	// Initialize description, sorted by default choice
	// - firstName name
	// - name
	// - firstName
	// - Company
	// Then cut at the first line feed
	if (gAddrP->fields[firstName])
	{
		if (gAddrP->fields[name])
		{			
			// If we have an alternate separator usage encoding 
			if (ToolsGetDisplayNameLayout(gAddrP->fields[firstName], gAddrP->fields[name], &nameLayoutFMap))

⌨️ 快捷键说明

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