📄 addrview.c
字号:
// Check if we word wrapped in the middle of a word which could
// fit on the next line. Word wrap doesn't work well for use
// when we call it twice on the same line.
// The first part checks to see if we stopped in the middle of a line
// The second part check to see if we didn't stop after a word break
// The third part checks if this line wasn't a wide as it could be
// because some other text used up space.
if (indentation < width && text[offset + length] != '\0')
{
WChar curChar;
TxtGetPreviousChar (text, offset + length, &curChar);
if (!TxtCharIsSpace(curChar))
{
length = 0; // don't word wrap - try next line
}
}
if (length == 0 && width == indentation && text[offset] != '\0')
{
length = TxtGetNextChar (text, offset, NULL);
}
if (0 < length)
{
// Lines returned from FldWordWrap may include a '\n' at the
// end. If present remove it to keep it from being drawn.
// The alternative is to not draw linefeeds at draw time. That
// seem more complex (there's many WinDrawChars) and slower as well.
// This way is faster but makes catching word wrapping problems
// less obvious (length 0 also happens when word wrap fails).
UInt16 newOffset = offset + length;
WChar prevChar;
TxtGetPreviousChar(text, newOffset, &prevChar);
if (prevChar == linefeedChr)
{
length--;
}
offset = newOffset;
}
RecordViewLines[RecordViewLastLine].length = length;
RecordViewLastLine++;
// Wrap to the start of the next line if there's still more text
// to draw (so we must have run out of room) or wrap if we
// encountered a line feed character.
if (text[offset] == '\0')
{
break;
}
width = indentation;
}
// If the last character was a new line then there is no width.
// Otherwise the width is the width of the characters on the last line.
if (offset)
TxtGetPreviousChar(text, offset, &lastChar);
else
lastChar = 0;
if (lastChar == linefeedChr)
{
width = 0;
}
else
{
if (RecordViewLastLine > 0)
width += FntCharsWidth (&text[RecordViewLines[RecordViewLastLine - 1].offset],
RecordViewLines[RecordViewLastLine - 1].length);
}
*widthPtr = width;
}
/***********************************************************************
*
* FUNCTION: PrvViewErase
*
* DESCRIPTION: Erases the record view
*
* PARAMETERS: nothing
*
* RETURNED: true if the event was handled and should not be passed
* to a higher level handler.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 6/30/95 Initial Revision
*
***********************************************************************/
void PrvViewErase( FormType* frmP )
{
RectangleType r;
FrmGetObjectBounds(frmP, FrmGetObjectIndex(frmP, RecordViewDisplay), &r);
WinEraseRectangle (&r, 0);
}
/***********************************************************************
*
* FUNCTION: PrvViewCalcNextLine
*
* DESCRIPTION: This routine returns the amount of extra vertical space
* required due to the item at this index in the lines array.
* If there are multiple items in the line array which go on
* the same y coordinate, the first is the one which
* contributes the vertical space requirement. Text which
* begins to the left of text on the previous line starts a
* new line. Blank lines use only a half line to save space.
*
* PARAMETERS: i - the line to base how far to advance
* oneLine - the amount which advance one line down.
*
* RETURNED: the amount to advance. Typically oneLine or oneLine / 2.
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 9/28/95 Initial Revision
* peter 10/06/00 Replaced description above.
*
***********************************************************************/
UInt16 PrvViewCalcNextLine(UInt16 i, UInt16 oneLine)
{
// Advance down if the text starts before the text of the current line.
if (RecordViewLines[i].x == 0 ||
(i > 0 &&
(RecordViewLines[i].x <= RecordViewLines[i - 1].x || RecordViewLines[i - 1].fieldNum == recordViewBlankLine)))
{
// A non blank line moves down a full line.
if (RecordViewLines[i].fieldNum != recordViewBlankLine)
{
return oneLine;
}
else
{
// A recordViewBlankLine is half-height.
return oneLine / 2;
}
}
return 0; // Stay on the same line.
}
/***********************************************************************
*
* FUNCTION: PrvViewDrawSelectedText
*
* DESCRIPTION: Inverts text which is considered selected.
*
* PARAMETERS: currentField - field containing the selected text
* selectPos - offset into field for start of selected text
* selectLen - length of selected text. This field
* should be zero if selected text isn't desired.
* textY - where on the screen the text was drawn
*
* RETURNED: nothing
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* roger 11/27/95 Cut from PrvViewDraw
* jmp 04-21-00 Fixed bug #23860: This routine was calling
* WInvertRectangle(), which produced somewhat unpredicatable
* results in a color environment. Changed the routine
* to call WinDrawInvertChars() instead, which swaps
* the foreground and background colors appropriately.
* peter 05/05/00 Remove code that tried but failed to extend selection rectangle 1 pixel.
* This code could be fixed, but we'd also need to erase the extra pixel.
* peter 05/17/00 Change to display text with selected object colors.
*
***********************************************************************/
void PrvViewDrawSelectedText (UInt16 currentField, UInt16 selectPos, UInt16 selectLen, UInt16 textY)
{
UInt16 selectXLeft = 0;
UInt16 selectXRight = 0;
// If the start of the selected region is on this line, calc an x.
if ( (RecordViewLines[currentField].offset <= selectPos) && (selectPos < RecordViewLines[currentField].offset + RecordViewLines[currentField].length) )
{
selectXLeft = FntCharsWidth(&recordViewRecord.fields[RecordViewLines[currentField].fieldNum][RecordViewLines[currentField].offset], selectPos - RecordViewLines[currentField].offset);
}
// If the end of the selected region is on this line, calc an x.
if ( (RecordViewLines[currentField].offset <= selectPos + selectLen) && (selectPos + selectLen <= RecordViewLines[currentField].offset + RecordViewLines[currentField].length))
{
selectXRight = FntCharsWidth(&recordViewRecord.fields[RecordViewLines[currentField].fieldNum][RecordViewLines[currentField].offset], selectPos + selectLen - RecordViewLines[currentField].offset);
}
// If either the left or right have been set then some
// text needs to be selected.
if (selectXLeft | selectXRight)
{
// Switch to selected object colors.
WinPushDrawState();
WinSetBackColor(UIColorGetTableEntryIndex(UIObjectSelectedFill));
WinSetForeColor(UIColorGetTableEntryIndex(UIObjectSelectedForeground));
WinSetTextColor(UIColorGetTableEntryIndex(UIObjectSelectedForeground));
// Draw the text with the selection colors.
WinDrawChars(&recordViewRecord.fields[RecordViewLines[currentField].fieldNum][selectPos], selectLen, selectXLeft += RecordViewLines[currentField].x, textY);
// Restore non-selected object colors.
WinPopDrawState();
}
}
/***********************************************************************
*
* FUNCTION: PrvViewDraw
*
* DESCRIPTION: This routine initializes the "Record View"
*
* PARAMETERS: selectFieldNum - field to show selected text
* selectPos - offset into field for start of selected text
* selectLen - length of selected text. This field
* should be zero if selected text isn't desired.
* drawOnlySelectField - whether one or all fields are drawn
*
* RETURNED: true if the event was handled and should not be passed
* to a higher level handler.
*
* HISTORY:
* 06/21/95 rsf Created by Roger Flores
* 02/06/98 tlw Change test below "If we are past bottom stop drawing" from
* if >= bottomOfRecordViewDisplay - FntLineHeight() to
* if > bottomOfRecordViewDisplay - FntLineHeight()
* to allow last line to be drawn.
* 07/29/99 kwk When drawing zip code, load prefix (# of spaces) from resource.
* 05/17/00 peter Explicitly set colors to draw in.
* 09/25/00 aro Adding frmP as an argument for the frmUpdateEvent
* 10/06/00 peter & danny When first line is blank, leave the 1/2 line gap used for blank lines.
* 11/28/00 FPa Fixed bug #45991
* 11/29/00 FPa Fixed bug #46272
*
***********************************************************************/
void PrvViewDraw ( FormType* frmP, UInt16 selectFieldNum, UInt16 selectPos, UInt16 selectLen, Boolean drawOnlySelectField )
{
AddrAppInfoPtr appInfoPtr;
UInt16 y;
UInt16 previousNonZeroHeight;
UInt16 currentHeight;
UInt16 i;
FontID curFont;
UInt16 phoneLabelNum;
Char * fieldLabelString;
UInt16 fieldLabelLength;
UInt16 upIndex;
UInt16 downIndex;
Boolean scrollableUp;
Boolean scrollableDown;
RectangleType r;
int bottomOfRecordViewDisplay;
#if USE_TEMPLATES
// First check if we draw using the layout.
if (PrvViewDrawUsingTemplate(frmP, selectFieldNum, selectPos, selectLen, drawOnlySelectField ))
return;
#endif
TraceOutput(TL(appErrorClass, "PrvViewDraw()"));
TraceOutput(TL(appErrorClass, "PrvViewDraw() - selectPos = %hu, selectLen = %hu", selectPos, selectLen));
appInfoPtr = (AddrAppInfoPtr) AddrDBAppInfoGetPtr(AddrDB);
FrmGetObjectBounds(frmP, FrmGetObjectIndex(frmP, RecordViewDisplay), &r);
bottomOfRecordViewDisplay = r.topLeft.y + r.extent.y;
// Set the background color in control-style colors since the text is selectable.
WinPushDrawState();
WinSetBackColor(UIColorGetTableEntryIndex(UIFieldBackground));
WinSetForeColor(UIColorGetTableEntryIndex(UIObjectForeground));
WinSetTextColor(UIColorGetTableEntryIndex(UIObjectForeground));
// Fill the entire record view display with the background color.
if (! drawOnlySelectField)
WinEraseRectangle(&r, 0);
if (TopRecordViewLine < RecordViewFirstPlainLine)
curFont = FntSetFont (largeBoldFont);
else
curFont = FntSetFont (AddrRecordFont);
y = r.topLeft.y;
previousNonZeroHeight = 0;
for (i = TopRecordViewLine; i < RecordViewLastLine; i++)
{
// Switch fonts if necessary before computing the extra vertical
// space needed for this element of the array.
if (i == RecordViewFirstPlainLine)
FntSetFont (AddrRecordFont);
currentHeight = PrvViewCalcNextLine(i, FntLineHeight());
// Since the above function returns zero for all but the first
// item when several should be drawn at the same y coordinate,
// we need to delay adding the result until we get to the next
// non-zero result.
if (currentHeight != 0)
{
y += previousNonZeroHeight;
previousNonZeroHeight = currentHeight;
}
// If we are past the bottom stop drawing
if (y > bottomOfRecordViewDisplay - FntLineHeight())
break;
ErrNonFatalDisplayIf(y < r.topLeft.y, "Drawing record out of gadget");
if (!drawOnlySelectField || RecordViewLines[i].fieldNum == selectFieldNum)
{
if (RecordViewLines[i].offset == 0)
{
switch (RecordViewLines[i].fieldNum)
{
case recordViewBlankLine:
break;
case phone1:
case phone2:
case phone3:
case phone4:
case phone5:
phoneLabelNum = GetPhoneLabel(&recordViewRecord, RecordViewLines[i].fieldNum);
fieldLabelString = appInfoPtr->fieldLabels[phoneLabelNum +
((phoneLabelNum < numPhoneLabelsStoredFirst) ? firstPhoneField : (addressFieldsCount - numPhoneLabelsStoredFirst))];
fieldLabelLength = StrLen(fieldLabelString);
WinDrawChars(fieldLabelString, fieldLabelLength, 0, y);
WinDrawChars(": ", 2, FntCharsWidth(fieldLabelString, fieldLabelLength), y);
WinDrawChars(&recordViewRecord.fields[RecordViewLines[i].fieldNum][RecordViewLines[i].offset], RecordViewLines[i].length, RecordViewLines[i].x, y);
break;
case custom1:
case custom2:
case custom3:
case custom4:
{
Int16 fieldLabelWidth;
Int16 fieldLabelCompleteWidth;
fieldLabelString = appInfoPtr->fieldLabels[RecordViewLines[i].fieldNum];
fieldLabelLength = StrLen(fieldLabelString);
fieldLabelWidth = FntCharsWidth(fieldLabelString, fieldLabelLength);
fieldLabelCompleteWidth = fieldLabelWidth + FntCharsWidth(": ", 2);
if (RecordViewLines[i].length == 0 || // If the custom label is displayed on a line and its content on the next line (because the custom label has been renamed using a long name and because it content is multi-line)
fieldLabelCompleteWidth <= RecordViewLines[i].x) // If the label name is not too width, then we display the label name and its content on the same line
{
WinDrawChars(fieldLabelString, fieldLabelLength, 0, y);
WinDrawChars(": ", 2, fieldLabelWidth, y);
}
WinDrawChars(&recordViewRecord.fields[RecordViewLines[i].fieldNum][RecordViewLines[i].offset], RecordViewLines[i].length, RecordViewLines[i].x, y);
break;
}
case state:
if (RecordViewLines[i].x > 0)
WinDrawChars(", ", 2, RecordViewLines[i].x - FntCharsWidth(", ", 2), y);
WinDrawChars(&recordViewRecord.fields[RecordViewLines[i].fieldNum][RecordViewLines[i].offset], RecordViewLines[i].length, RecordViewLines[i].x, y);
break;
case zipCode:
if (RecordViewLines[i].x > 0)
{
const Char* textP;
MemHandle zipCodePrefixH;
zipCodePrefixH = DmGetResource(strRsc, ZipCodePrefixStr);
textP = (const Char*)MemHandleLock(zipCodePrefixH);
WinDrawChars(textP, StrLen(textP), RecordViewLines[i].x - FntCharsWidth(textP, StrLen(textP)), y);
MemPtrUnlock((MemPtr)textP);
DmReleaseResource(zipCodePrefixH);
}
WinDrawChars(&recordViewRecord.fields[RecordViewLines[i].fieldNum][RecordViewLines[i].offset], RecordViewLines[i].length, RecordViewLines[i].x, y);
break;
default:
WinDrawChars(&recordViewRecord.fields[RecordViewLines[i].fieldNum][RecordViewLines[i].offset], RecordViewLines[i].length, RecordViewLines[i].x, y);
break;
}
}
else
{
// Draw the remainder of the fields' lines without any
// other special handling.
if (RecordViewLines[i].fieldNum != recordViewBlankLine)
{
WinDrawChars(&recordViewRecord.fields[RecordViewLines[i].fieldNum][RecordViewLines[i].offset], RecordViewLines[i].length, RecordViewLines[i].x, y);
}
}
// Highlight text if it is within the selection bounds. This is
// used to select found text and phone numbers when the user taps on them.
if ( (RecordViewLines[i].fieldNum == selectFieldNum) && (selectLen > 0) )
{
if ( selectPos < RecordViewLines[i].offset + RecordViewLines[i].length ) // If there's a selection to draw on this line (if the beginning of the selection is on this line or one of the previous lines)
{
UInt16 pos;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -