📄 addrtools.c
字号:
Int16 lowPriNameWidth;
Char fieldSeparatorStr[kMaxSeparatorStrLen+1];
Int16 fieldSeparatorLen;
ToolsSetupSeparators(name1, name2, fieldSeparatorStr, &fieldSeparatorLen, priorityIsName1);
// Check if both names fit
totalWidth = name1Width + (name2 ? fieldSeparatorWidth : 0) + name2Width;
// If we are supposed to center the names then move in the x position
// by the amount that centers the text
if (center && (nameExtent > totalWidth))
{
*x += (nameExtent - totalWidth) / 2;
}
// Special case if only name1 is given
if (name2 == NULL)
{
// Draw name portion that fits in extent
FntCharsInWidth(name1, (Int16*)&nameExtent, &name1Length, &ignored);
if (inTitle)
WinDrawInvertedChars(name1, name1Length, *x, y);
else
WinDrawChars(name1, name1Length, *x, y);
// Add width of characters actually drawn
*x += FntCharsWidth(name1, name1Length);
return;
}
// Remove name separator width
nameExtent -= fieldSeparatorWidth;
// Test if both names fit
if ((name1Width + name2Width) <= nameExtent)
{
name1MaxWidth = name1Width;
name2MaxWidth = name2Width;
}
else
{
// They dont fit. One or both needs truncation
// Establish name priorities and their allowed widths
// Change this to alter the ratio of the low and high priority name spaces
Int16 highPriMaxWidth = (nameExtent * 2) / 3; // 1/3 to low and 2/3 to high
Int16 lowPriMaxWidth = nameExtent - highPriMaxWidth;
// Save working copies of names and widths based on priority
if (priorityIsName1)
{
// Priority is name1
// highPriName = name1;
highPriNameWidth = name1Width;
lowPriName = name2;
lowPriNameWidth = name2Width;
}
else
{
// Priority is name2
// highPriName = name2;
highPriNameWidth = name2Width;
lowPriName = name1;
lowPriNameWidth = name1Width;
}
// Does high priority name fit in high priority max width?
if (highPriNameWidth > highPriMaxWidth)
{
// No. Look for word break in low priority name
Char * spaceP = StrChr(lowPriName, spaceChr);
if (spaceP != NULL)
{
// Found break. Set low priority name width to break width
lowPriNameWidth = FntCharsWidth(lowPriName, spaceP - lowPriName);
// Reclaim width from low pri name width to low pri max width, if smaller
if (lowPriNameWidth < lowPriMaxWidth)
{
lowPriMaxWidth = lowPriNameWidth;
// Set new high pri max width
highPriMaxWidth = nameExtent - lowPriMaxWidth;
}
}
}
else
{
// Yes. Adjust maximum widths
highPriMaxWidth = highPriNameWidth;
lowPriMaxWidth = nameExtent - highPriMaxWidth;
}
// Convert priority widths back to name widths
if (priorityIsName1)
{
// Priority is name1
name1Width = highPriNameWidth;
name2Width = lowPriNameWidth;
name1MaxWidth = highPriMaxWidth;
name2MaxWidth = lowPriMaxWidth;
}
else
{
// Priority is name2
name1Width = lowPriNameWidth;
name2Width = highPriNameWidth;
name1MaxWidth = lowPriMaxWidth;
name2MaxWidth = highPriMaxWidth;
}
}
// Does name1 fit in its maximum width?
if (name1Width > name1MaxWidth)
{
// No. Draw it to max width minus the ellipsis
name1Width = name1MaxWidth - shortenedFieldWidth;
FntCharsInWidth(name1, &name1Width, &name1Length, &ignored);
if (inTitle)
WinDrawInvertedChars(name1, name1Length, *x, y);
else
WinDrawChars(name1, name1Length, *x, y);
*x += name1Width;
// Draw ellipsis
if (inTitle)
WinDrawInvertedChars(shortenedFieldString, shortenedFieldLength, *x, y);
else
WinDrawChars(shortenedFieldString, shortenedFieldLength, *x, y);
*x += shortenedFieldWidth;
}
else
{
// Yes. Draw name1 within its width
FntCharsInWidth(name1, &name1Width, &name1Length, &ignored);
if (inTitle)
WinDrawInvertedChars(name1, name1Length, *x, y);
else
WinDrawChars(name1, name1Length, *x, y);
*x += name1Width;
}
// Draw name separator
if (inTitle)
WinDrawInvertedChars(fieldSeparatorStr, fieldSeparatorLen, *x, y);
else
WinDrawChars(fieldSeparatorStr, fieldSeparatorLen, *x, y);
*x += fieldSeparatorWidth;
// Draw name2 within its maximum width
FntCharsInWidth(name2, &name2MaxWidth, &name2Length, &ignored);
if (inTitle)
WinDrawInvertedChars(name2, name2Length, *x, y);
else
WinDrawChars(name2, name2Length, *x, y);
*x += name2MaxWidth;
}
/***********************************************************************
*
* FUNCTION: ToolsDrawRecordNameAndPhoneNumber
*
* DESCRIPTION: Draws the name and phone number (plus which phone)
* within the screen bounds passed.
*
* PARAMETERS: record - record to draw
* bounds - bounds of the draw region
* phoneLabelLetters - the first letter of each phone label
* sortByCompany - true if the database is sorted by company
* unnamedRecordStringPtr - string to use for unnamed records
*
* RETURNED: x coordinate where phone number starts
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 6/21/95 Initial Revision
* peter 5/09/00 Added result and eliminated destructive change to bounds
* fpa 11/02/00 Added unnamedRecordStringH parameter in order to prevent memory leaks
*
***********************************************************************/
Int16 ToolsDrawRecordNameAndPhoneNumber(AddrDBRecordPtr record, RectanglePtr bounds, WChar * phoneLabelLetters, Boolean sortByCompany, Char **unnamedRecordStringPtr, MemHandle* unnamedRecordStringH)
{
Int16 x, y, phoneX, widthWithoutPhoneLabel;
UInt16 phoneLabel;
Int16 fieldSeparatorWidth;
Int16 shortenedFieldWidth;
Char * name1;
Char * name2;
Char * phone;
Int16 name1Length;
Int16 name2Length;
Int16 phoneLength;
Int16 name1Width;
Int16 name2Width;
Int16 phoneWidth;
UInt16 nameExtent;
Boolean ignored;
Boolean name1HasPriority;
UInt8 phoneLabelWidth;
const Int16 phoneColumnWidth = maxPhoneColumnWidth;
Char fieldSeparatorStr[kMaxSeparatorStrLen+1];
Int16 fieldSeparatorLen;
x = bounds->topLeft.x;
y = bounds->topLeft.y;
phoneLabelWidth = ToolsGetPhoneLabelWidth() - 1; // remove the blank trailing column
widthWithoutPhoneLabel = bounds->extent.x - (phoneLabelWidth + 1);
name1HasPriority = ToolsDetermineRecordName(record, &shortenedFieldWidth, &fieldSeparatorWidth, sortByCompany, &name1, &name1Length, &name1Width, &name2, &name2Length, &name2Width, unnamedRecordStringPtr, unnamedRecordStringH, widthWithoutPhoneLabel);
phone = record->fields[phone1 + record->options.phones.displayPhoneForList];
if (phone)
{
// Only show text from the first line in the field
phoneWidth = widthWithoutPhoneLabel;
phoneLength = phoneWidth; // more characters than we can expect
FntCharsInWidth (phone, &phoneWidth, &phoneLength, &ignored);
}
else
{
phoneLength = 0;
phoneWidth = 0;
}
phoneX = bounds->topLeft.x + widthWithoutPhoneLabel - phoneWidth;
// Set up the separators for the drawing
ToolsSetupSeparators(name1, name2, fieldSeparatorStr, &fieldSeparatorLen, name1HasPriority);
if (widthWithoutPhoneLabel >= name1Width + (name2 ? fieldSeparatorWidth : 0) +
name2Width + (phone ? spaceBetweenNamesAndPhoneNumbers : 0) + phoneWidth)
{
// we can draw it all!
WinDrawChars(name1, name1Length, x, y);
x += name1Width;
// Is there a second name?
if (name2)
{
if (name1)
{
WinDrawChars(fieldSeparatorStr, fieldSeparatorLen, x, y);
x += fieldSeparatorWidth;
}
// draw name2
WinDrawChars(name2, name2Length, x, y);
x += name2Width;
}
if (phone)
WinDrawChars(phone, phoneLength, phoneX, y);
}
else
{
// Shortened math (970812 maf)
nameExtent = widthWithoutPhoneLabel - min(phoneWidth, phoneColumnWidth);
// Leave some space between names and numbers if there is a phone number
if (phone)
nameExtent -= spaceBetweenNamesAndPhoneNumbers;
ToolsDrawRecordName (name1, name1Length, name1Width, name2, name2Length, name2Width,
nameExtent, &x, y, shortenedFieldWidth, fieldSeparatorWidth, false,
name1HasPriority || !sortByCompany, false);
if (phone)
{
x += spaceBetweenNamesAndPhoneNumbers;
nameExtent = x - bounds->topLeft.x;
// Now draw the phone number
if (widthWithoutPhoneLabel - nameExtent >= phoneWidth)
// We can draw it all
WinDrawChars(phone, phoneLength, phoneX, y);
else
{
// The phone number should be right justified instead of using
// x from above because the string printed may be shorter
// than we expect (CharsInWidth chops off space chars).
phoneWidth = widthWithoutPhoneLabel - nameExtent - shortenedFieldWidth;
FntCharsInWidth(phone, &phoneWidth, &phoneLength, &ignored);
phoneX = bounds->topLeft.x + widthWithoutPhoneLabel - shortenedFieldWidth - phoneWidth;
WinDrawChars(phone, phoneLength, phoneX, y);
WinDrawChars(shortenedFieldString, shortenedFieldLength,
bounds->topLeft.x + widthWithoutPhoneLabel - shortenedFieldWidth, y);
}
}
}
if (phone)
{
// Draw the first letter of the phone field label
phoneLabel = GetPhoneLabel(record, firstPhoneField +
record->options.phones.displayPhoneForList);
// find out if the first letter of the phone label is an O(ther) or
// E(mail). If it is email don't draw the letter. If it is other, and the
// contents of the phone field is not a number, don't draw the letter.
if ( phoneLabel != emailLabel )
{
if ( (phoneLabel != otherLabel) || PrvToolsPhoneIsANumber (phone) )
{
WinDrawChar (phoneLabelLetters[phoneLabel],
bounds->topLeft.x + widthWithoutPhoneLabel + 1 + ((phoneLabelWidth -
(FntWCharWidth(phoneLabelLetters[phoneLabel]) - 1)) >> 1), y);//lint !e702
}
}
}
return phoneX;
}
/***********************************************************************
*
* FUNCTION: ToolsGetLabelColumnWidth
*
* DESCRIPTION: Calculate the width of the widest field label plus a ':'.
*
* PARAMETERS: appInfoPtr - pointer to the app info block for field labels
* labelFontID - font
*
* RETURNED: width of the widest label.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 1/30/98 Initial Revision
* vsm 1/15/03 Use ": " instead of ':' + 1 as the suffix string
* whose width is added on to the label width since
* that is what is used by the record view.
***********************************************************************/
UInt16 ToolsGetLabelColumnWidth (AddrAppInfoPtr appInfoPtr, FontID labelFontID)
{
Int16 i;
UInt16 labelWidth; // Width of a field label
UInt16 columnWidth; // Width of the label column (fits all label)
FontID curFont;
Char * label;
// Calculate column width of the label column which is used by the Record View and the
// Edit View.
curFont = FntSetFont (labelFontID);
columnWidth = 0;
for (i = firstAddressField; i < lastLabel; i ++)
{
label = appInfoPtr->fieldLabels[i];
labelWidth = FntCharsWidth(label, StrLen(label));
columnWidth = max(columnWidth, labelWidth);
}
columnWidth += 1+ FntCharsWidth(": ", 2);
FntSetFont (curFont);
if (columnWidth > maxLabelColumnWidth)
columnWidth = maxLabelColumnWidth;
return columnWidth;
}
/***********************************************************************
*
* FUNCTION: ToolsLeaveForm
*
* DESCRIPTION: Leaves the current popup form and returns to the prior one.
*
* PARAMETERS: formID - resource id of form to return to
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 6/30/95 Initial Revision
*
***********************************************************************/
void ToolsLeaveForm ()
{
FormPtr frm;
frm = FrmGetActiveForm();
FrmEraseForm (frm);
FrmDeleteForm (frm);
FrmSetActiveForm (FrmGetFirstForm ());
}
/***********************************************************************
*
* FUNCTION: ToolsChangeCategory
*
* DESCRIPTION: This routine updates the global varibles that keep track
* of category information.
*
* PARAMETERS: category - new category (index)
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/5/95 Initial Revision
*
***********************************************************************/
void ToolsChangeCategory (UInt16 category)
{
CurrentCategory = category;
TopVisibleRecord = 0;
}
/***********************************************************************
*
* FUNCTION: ToolsSeekRecord
*
* DESCRIPTION: Given the index of a to do record, this routine scans
* forewards or backwards for displayable to do records.
*
* PARAMETERS: indexP - pointer to the index of a record to start from;
* the index of the record sought is returned in
* this parameter.
*
* offset - number of records to skip:
* 0 - mean seek from the current record to the
* next display record, if the current record is
* a display record, its index is retuned.
* 1 - mean seek foreward, skipping one displayable
* record
* -1 - means seek backwards, skipping one
* displayable record
*
*
* RETURNED: false is return if a displayable record was not found.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/5/95 Initial Revision
*
***********************************************************************/
Boolean ToolsSeekRecord (UInt16 * indexP, Int16 offset, Int16 direction)
{
DmSeekRecordInCategory (AddrDB, indexP, offset, direction, CurrentCategory);
if (DmGetLastErr()) return (false);
return (true);
}
/***********************************************************************
*
* FUNCTION: ToolsDirtyRecord
*
* DESCRIPTION: Mark a record dirty (modified). Record marked dirty
* will be synchronized.
*
* PARAMETERS:
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/5/95 Initial Revision
*
***********************************************************************/
void ToolsDirtyRecord (UInt16 index)
{
UInt16 attr;
DmRecordInfo (AddrDB, index, &attr, NULL, NULL);
attr |= dmRecAttrDirty;
DmSetRecordInfo (AddrDB, index, &attr, NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -