📄 addrdiallist.c
字号:
/******************************************************************************
*
* 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 + -