📄 addrtools.c
字号:
/***********************************************************************
*
* FUNCTION: ToolsSelectFont
*
* DESCRIPTION: This routine handles selection of a font
*
* PARAMETERS: currFontID - id of current font
*
* RETURNED: id of new font
*
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 9/10/97 Initial Revision
*
***********************************************************************/
FontID ToolsSelectFont (FontID currFontID)
{
UInt16 formID;
FontID fontID;
formID = (FrmGetFormId (FrmGetActiveForm ()));
// Call the OS font selector to get the id of a font.
fontID = FontSelect (currFontID);
if (fontID != currFontID)
FrmUpdateForm (formID, updateFontChanged);
return (fontID);
}
/***********************************************************************
*
* FUNCTION: ToolsDeleteRecord
*
* DESCRIPTION: Deletes an address record.
*
* PARAMETERS: nothing
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 6/13/95 Initial Revision
* grant 6/21/99 Unlock the record if it is being archived.
* jwm 1999-10-8 Swap forward/backward so users can work
* through deleting records from top to bottom.
*
***********************************************************************/
void ToolsDeleteRecord (Boolean archive)
{
// Show the following record. Users want to see where the record was and
// they also want to return to the same location in the database because
// they might be working their way through the records. If there isn't
// a following record show the prior record. If there isn't a prior
// record then don't show a record.
ListViewSelectThisRecord = CurrentRecord;
if (!ToolsSeekRecord(&ListViewSelectThisRecord, 1, dmSeekForward))
if (!ToolsSeekRecord(&ListViewSelectThisRecord, 1, dmSeekBackward))
ListViewSelectThisRecord = noRecord;
// Delete or archive the record.
if (archive)
{
DmArchiveRecord (AddrDB, CurrentRecord);
}
else
DmDeleteRecord (AddrDB, CurrentRecord);
// Deleted records are stored at the end of the database
DmMoveRecord (AddrDB, CurrentRecord, DmNumRecords (AddrDB));
// Since we just moved the CurrentRecord to the end the
// ListViewSelectThisRecord may have been moved up one position.
if (ListViewSelectThisRecord >= CurrentRecord &&
ListViewSelectThisRecord != noRecord)
ListViewSelectThisRecord--;
// Use whatever record we found to select.
CurrentRecord = ListViewSelectThisRecord;
}
/***********************************************************************
*
* FUNCTION: ToolsCustomAcceptBeamDialog
*
* DESCRIPTION: This routine uses uses a new exchange manager function to
* Ask the user if they want to accept the data as well as set
* the category to put the data in. By default all data will go
* to the unfiled category, but the user can select another one.
* We store the selected category index in the appData field of
* the exchange socket so we have it at the when we get the receive
* data launch code later.
*
* PARAMETERS: dbP - open database that holds category information
* askInfoP - structure passed on exchange ask launchcode
*
* RETURNED: Error if any
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* bhall 9/7/99 Initial Revision
* gavin 11/9/99 Rewritten to use new ExgDoDialog function
*
***********************************************************************/
Err ToolsCustomAcceptBeamDialog(DmOpenRef dbP, ExgAskParamPtr askInfoP)
{
ExgDialogInfoType exgInfo;
Err err;
Boolean result;
// set default category to unfiled
exgInfo.categoryIndex = dmUnfiledCategory;
// Store the database ref into a gadget for use by the event handler
exgInfo.db = dbP;
// Let the exchange manager run the dialog for us
result = ExgDoDialog(askInfoP->socketP, &exgInfo, &err);
if (!err && result) {
// pretend as if user hit OK, we'll now accept the data
askInfoP->result = exgAskOk;
// Stuff the category index into the appData field
askInfoP->socketP->appData = exgInfo.categoryIndex;
} else {
// pretend as if user hit cancel, we won't accept the data
askInfoP->result = exgAskCancel;
}
return err;
}
/***********************************************************************
*
* FUNCTION: ToolsGetObjectPtr
*
* DESCRIPTION: This routine returns a pointer to an object in the current
* form.
*
* PARAMETERS: formId - id of the form to display
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/5/95 Initial Revision
*
***********************************************************************/
void* ToolsGetObjectPtr (UInt16 objectID)
{
return ToolsGetFrmObjectPtr(FrmGetActiveForm(), objectID);
}
/***********************************************************************
*
* FUNCTION: ToolsGetFrmObjectPtr
*
* DESCRIPTION: This routine returns a pointer to an object
*
* PARAMETERS: frmP - form
* Id - id of the object to display,
*
* RETURNED: pointer to the object
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* aro 6/12/00 Initial Revision
*
***********************************************************************/
void* ToolsGetFrmObjectPtr( FormType* frmP, DmResID id )
{
return (FrmGetObjectPtr(frmP, FrmGetObjectIndex(frmP, id)));
}
/***********************************************************************
*
* FUNCTION: ToolsAddrBeamBusinessCard
*
* DESCRIPTION: Send the Business Card record or complain if none selected.
*
* PARAMETERS: dbP - the database
*
* RETURNED: true if the record is found and sent
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 10/20/97 Initial Revision
*
***********************************************************************/
Boolean ToolsAddrBeamBusinessCard (DmOpenRef dbP)
{
UInt16 recordNum;
if (DmFindRecordByID (AddrDB, BusinessCardRecordID, &recordNum) == dmErrUniqueIDNotFound ||
DmQueryRecord(dbP, recordNum) == 0)
FrmAlert(SendBusinessCardAlert);
else
{
TransferSendRecord(dbP, recordNum, exgBeamPrefix, NoDataToBeamAlert);
return true;
}
return false;
}
/***********************************************************************
*
* FUNCTION: ToolsInitPhoneLabelLetters
*
* DESCRIPTION: Init the list of first letters of phone labels. Used
* in the list view and for find.
*
* PARAMETERS: appInfoPtr - contains the field labels
* phoneLabelLetters - array of characters (one for each phone label)
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 7/24/95 Initial Revision
*
***********************************************************************/
#if 0
void ToolsInitPhoneLabelLetters(AddrAppInfoPtr appInfoPtr, Char * phoneLabelLetters)
{
UInt16 i;
// Get the first char of the phone field labels for the list view.
for (i = 0; i < numPhoneLabels; i++){
phoneLabelLetters[i] = appInfoPtr->fieldLabels[i +
((i < numPhoneLabelsStoredFirst) ? firstPhoneField :
(addressFieldsCount - numPhoneLabelsStoredFirst))][0];
}
}
#else
void ToolsInitPhoneLabelLetters (AddrAppInfoPtr appInfoPtr, WChar *phoneLabelLetters)
{
UInt16 i;
WChar ch;
// Get the first Char of the phone field labels for the list view.
for (i = 0; i < numPhoneLabels; ++i)
{
Char *src = appInfoPtr->fieldLabels[i + (i < numPhoneLabelsStoredFirst
? firstPhoneField
: addressFieldsCount - numPhoneLabelsStoredFirst)];
TxtGetNextChar(src, 0, &ch);
phoneLabelLetters[i] = ch;
}
}
#endif
/***********************************************************************
*
* FUNCTION: ToolsDuplicateCurrentRecord
*
* DESCRIPTION: Duplicates a new record from the current record.
*
* PARAMETERS: numCharsToHilite (Output): The number of characters added to the
* first name field to indicate that it was a duplicated record.
*
* RETURNED: The number of the new duplicated record.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* css 6/13/99 Initial Revision
* vsm 11/06/02 Set the EditRowIDWhichHadFocus based on the
* field map rather than on "lucky coincidence".
*
***********************************************************************/
UInt16 ToolsDuplicateCurrentRecord (UInt16 *numCharsToHilite, Boolean deleteCurrentRecord)
{
AddrDBRecordType recordToDup;
UInt16 attr;
Err err;
UInt16 newRecordNum;
MemHandle recordH;
char *newFirstName = NULL;
char duplicatedRecordIndicator [maxDuplicatedIndString + 1];
UInt16 sizeToGet;
UInt16 oldFirstNameLen;
AddressFields fieldToAdd = firstName;
AddressFields* fMapP;
MemHandle fMapH;
Int16 i;
AddrDBGetRecord (AddrDB, CurrentRecord, &recordToDup, &recordH);
// Now we must add the "duplicated indicator" to the end of the First Name so that people
// know that this was the duplicated record.
ToolsGetStringResource (DuplicatedRecordIndicatorStr, duplicatedRecordIndicator);
*numCharsToHilite = StrLen (duplicatedRecordIndicator);
// Find the first non-empty field from (first name, last name, company) to add "copy" to.
fieldToAdd = firstName;
if (recordToDup.fields[fieldToAdd] == NULL)
fieldToAdd = name;
if (recordToDup.fields[fieldToAdd] == NULL)
fieldToAdd = company;
// revert to last name if no relevant fields exist
if (recordToDup.fields[fieldToAdd] == NULL)
fieldToAdd = name;
if (recordToDup.fields[fieldToAdd] == NULL)
{
recordToDup.fields[fieldToAdd] = duplicatedRecordIndicator;
}
else
{
// Get enough space for current string, one blank and duplicated record
// indicator string & end of string char.
oldFirstNameLen = StrLen (recordToDup.fields[fieldToAdd]);
sizeToGet = oldFirstNameLen + sizeOf7BitChar(spaceChr)+ StrLen (duplicatedRecordIndicator) + sizeOf7BitChar(nullChr);
newFirstName = MemPtrNew (sizeToGet);
if (newFirstName == NULL)
{
FrmAlert (DeviceFullAlert);
newRecordNum = noRecord;
goto Exit;
}
// make the new first name string with what was already there followed by
// a space and the duplicate record indicator string.
StrPrintF (newFirstName, "%s %s", recordToDup.fields[fieldToAdd], duplicatedRecordIndicator);
recordToDup.fields[fieldToAdd] = newFirstName;
// Must increment for the blank space that we add.
(*numCharsToHilite)++;
// Make sure that this string is less than or equal to the maximum allowed for
// the field.
if (StrLen (newFirstName) > maxNameLength)
{
newFirstName [maxNameLength] = '\0';
(*numCharsToHilite) = maxNameLength - oldFirstNameLen;
}
}
#if 0
EditRowIDWhichHadFocus = fieldToAdd; //this is a lucky coincidence, that the first two
//enums are the first two rows, but:
if (EditRowIDWhichHadFocus == company) //the third one's not
EditRowIDWhichHadFocus++;
#else
// Lucky coincidence doesn't work on localized versions. Instead use the field map
// resource to get the row ID.
fMapH = DmGetResource(fieldMapRscType, FieldMapID);
fMapP = (AddressFields*)MemHandleLock(fMapH);
for (i = 0; i < addressFieldsCount; i++)
{
if (fMapP[i] == fieldToAdd)
{
EditRowIDWhichHadFocus = i;
break;
}
}
MemHandleUnlock(fMapH);
ErrNonFatalDisplayIf(i == addressFieldsCount, "EditRowIDWhichHadFocus not set");
#endif
MemHandleUnlock(recordH);
// Make sure the attributes of the new record are the same.
DmRecordInfo (AddrDB, CurrentRecord, &attr, NULL, NULL);
// If we are to delete the current record, then lets do that now. We have
// all the information from the record that we need to duplicate it correctly.
if (deleteCurrentRecord)
{
ToolsDeleteRecord (false);
}
// Now create the new record that has been duplicated from the current record.
err = AddrDBNewRecord(AddrDB, &recordToDup, &newRecordNum);
if (err)
{
FrmAlert(DeviceFullAlert);
newRecordNum = noRecord;
goto Exit;
}
// This includes the catagory so the catagories are the same between the original and
// duplicated record.
attr |= dmRecAttrDirty;
DmSetRecordInfo (AddrDB, newRecordNum, &attr, NULL);
Exit:
if (newFirstName)
{
MemPtrFree (newFirstName);
}
return (newRecordNum);
}
/*****************************************************************************
* Function: ToolsGetStringResource
*
* Description: Reads the string associated with the resource into the passed
* in string.
*
* Notes: None.
*
* Parameters: stringResource: (Input) The string resource to be read.
* stringP: (Output) The string that represents the resource.
*
* Return Value(s): The address of the string that contains a copy of the resource string.
******************************************************************************/
char* ToolsGetStringResource (UInt16 stringResource, char * stringP)
{
MemHandle nameH;
nameH = DmGetResource(strRsc, stringResource);
StrCopy (stringP, (Char *) MemHandleLock (nameH));
MemHandleUnlock (nameH);
DmReleaseResource (nameH);
return (stringP);
}
/***********************************************************************
*
* FUNCTION:
* ToolsIsPhoneIndexSupported
*
* DESCRIPTION:
* This routine check if a the phone index of the given record has
* a type that allows dialing (ie for now all except email)
*
* PARAMETERS:
* recordP IN record pointer
* phoneIndex IN index of the phone to check, kDialListShowInListPhoneIndex
* for show in list
*
* RETURNED:
* true if the type is supported and if its content is not null
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* aro 6/27/00 Initial Revision
*
***********************************************************************/
Boolean ToolsIsPhoneIndexSupported( AddrDBRecordType* addrP, UInt16 phoneIndex )
{
UInt16 label;
UInt16 fieldIndex;
if (phoneIndex == kDialListShowInListPhoneIndex)
{
phoneIndex = addrP->options.phones.displayPhoneForList;
}
fieldIndex = firstPhoneField + phoneIndex;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -