📄 richtexthandling.c
字号:
/** eus_ReplaceRtfSpanText( ***
Purpose is to replace an identified span of rich text with the contents of the
provided, null-terminated text buffer.
--- parameters & return ------
pt_spn: Input & Output. Pointer to a rich-text span structure which holds the
beginning co鰎dinates of the span to be replaced, and optionally, the
ending co鰎dinates. If the ul_LEN_TEXT_TO_REPLACE parameter is provided,
passed-in ending co鰎dinates are ignored and will be reset according to the
dimension of that parameter. Output tells replacement span.
ul_LEN_TXT_TO_REPL: Optional. The length of the text to in the rich-text field
to be replaced. Parameter required if null ending co鰎dinates are provided
in the pt_spn parameter.
f_TRANSLT_LF: flag specifying whether rich-text linefeed and paragraph markers
should be translated to CRLFs when assessing content (TRUE) or not (FALSE)
PC: the replacement text content, null-terminated
pt_ctx: Input & Output. Pointer to tracking information about the operative
rich-text field.
RETURN:
eus_SUCCESS if no errors occurred
eus_ERR_INVLD_ARG if any passed-in parameter is obviously invalid
the Notes API error code otherwise
--- suggested enhancement ----
9/6/02 PR: um, code out PDL'd logic
--- revision history ---------
9/6/02 PR
+ implemented replacement-span output
+ listing format adjustment, minor safety improvement, token renaming,
documentation adjustment
3/20/00 PR
+ fixed bug wherein content to be preserved in an ending CDTEXT was not being
handled properly
+ logic shortening, some by leveraging the new UnlockItem() procedure
9/12/99 PR
+ added support for replacement content in excess of MAXONESEGSIZE
+ documentation adjustment
12/8/98 PR: created */
STATUS eus_ReplaceRtfSpanText( CdRecordSpan *const pt_spn,
const DWORD ul_LEN_TXT_TO_REPL,
const BOOL f_TRANSLT_LF,
const char PC[],
RtfTrackingInfo *const pt_ctx) {
CdRecordCursor t_crsrBgin, t_crsrEnd, t_crsr;
WORD us_offstEnd = NULL, us_lenEndPrsrv = NULL;
BYTE * puc, * puc_bgnSpnCdRec;
DWORD ul_lenRepl, ul;
STATUS us_err;
BOOL f_OneRcrdSpn = FALSE, f_ItmJustLockd;
//If any of the parameters are obviously invalid, short-circuit with
// general failure. A valid span requires either a content length or a
// valid end cursor.
if (!( pt_spn && PC && pt_ctx && pt_spn->t_crsrBgin.pt_item &&
pt_spn->t_crsrBgin.puc_location &&
(pt_spn->t_crsrEnd.puc_location &&
pt_spn->t_crsrEnd.pt_item ||
ul_LEN_TXT_TO_REPL) &&
(pt_spn->t_crsrBgin.pt_item ==
pt_spn->t_crsrEnd.pt_item ?
pt_spn->t_crsrBgin.puc_location <
pt_spn->t_crsrEnd.puc_location : TRUE)))
return eus_ERR_INVLD_ARG;
//now that the input seems okay, it's safe to initialize certain local
// variables
t_crsrBgin = pt_spn->t_crsrBgin;
puc_bgnSpnCdRec = t_crsrBgin.puc_location;
t_crsrEnd = pt_spn->t_crsrEnd;
if (t_crsrEnd.puc_location && *t_crsrEnd.puc_location == muc_SIG_CDTEXT)
us_offstEnd = pt_spn->us_offstEnd;
//determine the length of the replacement content, accounting if needed for
// CRLF to rich-text linefeed conversion
if (f_TRANSLT_LF)
TranslateCrlfText( PC, NULL, &ul_lenRepl, NULL, NULL);
else
ul_lenRepl = strlen( PC);
//if the passed-in span is marked by offset instead of end cursor,
// determine the appropriate end-cursor configuration
if (ul_LEN_TXT_TO_REPL && !f_ProcessKnownLengthRtfText( t_crsrBgin,
pt_spn->us_offstBgin,
ul_LEN_TXT_TO_REPL, f_TRANSLT_LF,
pt_ctx, &t_crsrEnd, &us_offstEnd, NULL))
return !eus_SUCCESS;
_ASSERTE( t_crsrEnd.puc_location);
//if a question, determine the length of text to preserve in the ending
// CDTEXT record, and whether we're dealing with a span that involves only
// one CDTEXT record and can be replaced with only one CDTEXT record
ul = sizeof( CDTEXT) + ul_lenRepl;
if (*t_crsrEnd.puc_location == muc_SIG_CDTEXT) {
us_lenEndPrsrv = t_crsrEnd.us_recLength - (sizeof( CDTEXT) +
us_offstEnd);
f_OneRcrdSpn = *puc_bgnSpnCdRec == muc_SIG_CDTEXT && puc_bgnSpnCdRec ==
t_crsrEnd.puc_location && ul +
pt_spn->us_offstBgin + us_lenEndPrsrv <=
mus_LENLIMIT_CDTEXT_REC;
}
//if the starting CD record of the span is not virtualized...
if (t_crsrBgin.pt_item->i_type != mi_VIRTUAL) {
//Virtualize up through the CD record preceding the starting CD record
// involved in the span. The actual frontier absolute offset will then
// point to the starting CD record.
if (us_err = us_VirtualizeThruActualLocation( puc_bgnSpnCdRec, pt_ctx,
NULL))
return us_err;
//Else we have to deal with already virtualized content. And that's a lot
// of complicated work.
}else {
return !eus_SUCCESS; //PGP development shortcut
//if the CD record following the span's ending CD record resides on an
// item different from the item containing the starting CD record...
//if the item containing the starting CD record is not the last
// virtual item, set the virtuality member of a proxy
// item-tracking structure to a copy of the item structure
// associated with the starting CD record's item but with a null
// next-item pointer
//if the starting CD record is not the first record in the item...
//reset the length of the item to point to the end of the CD
// record preceding the starting CD record
//else reset the length of the item to point to the beginning of
// the item (i.e. no item content at this point)
//else we need to recast the item bounding the rich-text span
//in a proxy item-tracking structure, create an initial virtual
// item and initialize it with the content on the item containing
// the starting CD record that precedes the starting record
//set an internal flag telling this procedure to nullify the beginning
// cursor in the passed-in span structure to indicate its invalidity
// to the caller
} //if (t_crsrBgin.pt_item->i_type != mi_VIRTUAL)
//if the starting co鰎dinates of the span to be replaced fall within, not
// at the beginning of, a CDTEXT...
if (*puc_bgnSpnCdRec == muc_SIG_CDTEXT && pt_spn->us_offstBgin) {
WORD us;
CdRecordCursor t_newStart;
//determine the tentative length of the first replacement CDTEXT as the
// sum of the length of a CDTEXT structure, the length of the content
// which precedes the the beginning of the span in the initial CDTEXT,
// the length of our replacement text, and if the ending co鰎dinates
// of the span fall within the same CDTEXT as the starting co鰎dinates
// do, the length of the content following the end of the span --
// tentative because the length cannot exceed the length limit we're
// observing on CDTEXT records.
ul += pt_spn->us_offstBgin;
if (f_OneRcrdSpn)
ul += us_lenEndPrsrv;
//get a pointer at which we can virtualize a CDTEXT CD record of the
// length just determined or of our limit length
us = ul < mus_LENLIMIT_CDTEXT_REC ? (WORD) ul : mus_LENLIMIT_CDTEXT_REC;
_ASSERTE( f_OneRcrdSpn ? ul == us : TRUE);
if (us_err = us_GetVirtualCdRecAppendPointer( pt_ctx, us, &puc))
return us_err;
//Virtualize the initial CDTEXT structure that accounts for its
// ultimate length, content included. Utilize the CDTEXT associated
// with the beginning of the rich-text span to preserve the font
// signature.
memcpy( puc, puc_bgnSpnCdRec, sizeof( CDTEXT));
((CDTEXT *) puc)->Header.Length = us;
//virtualize the content that precedes the beginning of the span in the
// initial CDTEXT
memcpy( puc + sizeof( CDTEXT), puc_bgnSpnCdRec + sizeof( CDTEXT),
pt_spn->us_offstBgin);
//Virtualize the replacement content, initializing the replacement-span
// output along the way.
t_newStart.puc_location = puc;
t_newStart.pt_item = pt_ctx->pt_endVirtual;
t_newStart.us_recLength = us;
if (us_err = us_AppendTextToVirtuality( PC, ul_lenRepl, f_TRANSLT_LF,
&t_newStart, pt_spn->us_offstBgin,
NULL, pt_ctx, pt_spn))
return us_err;
//if the ending co鰎dinates of the span fall within the same CDTEXT
// that the starting co鰎dinates do...
if (f_OneRcrdSpn) {
//tack on the content following the end of the span
memcpy( puc + ul - us_lenEndPrsrv, puc_bgnSpnCdRec + sizeof(
CDTEXT) + us_offstEnd + 1, us_lenEndPrsrv);
//set the ending-offset co鰎dinate of the replacement-span output
pt_spn->us_offstEnd = (WORD) (ul - us_lenEndPrsrv -
sizeof( CDTEXT));
//done with the virtualization of the CDTEXT, update the variable
// that tracks the length of the virtual item being written to
pt_ctx->pt_endVirtual->ul_length +=
pt_ctx->pt_endVirtual->ul_length % 2 + ul;
} //if (f_OneRcrdSpn)
//else we construct our own CDTEXTs to hold the replacement content
}else {
//PGP development shortcut: assuming that the first record in the span is a
// CDTEXT. If it's not, return general failure.
if (*puc_bgnSpnCdRec != muc_SIG_CDTEXT)
return !eus_SUCCESS;
//Determine a FONTID that we can use in the CDTEXT we need to write.
// Basically, we want the closest CDTEXT before (and including) the
// beginning of the span. If one isn't available, we want the closest
// one after the beginning CD record of the span (even if it's in the
// span). If no CDTEXTs are available at all, we will use the Notes
// default FONTID.
//PGP development shortcut: using the beginning, source CDTEXT's FONTID
//virtualize the replacement content and note the span of the added
// rich-text
if (us_err = us_AppendTextToVirtuality( PC, ul_lenRepl, f_TRANSLT_LF,
NULL, NULL, ((CDTEXT *)
puc_bgnSpnCdRec)->FontID, pt_ctx, pt_spn))
return us_err;
} //if (*t_crsrBgin.puc_location == LOBYTE(
//if some of the content in the CD record pointed to by the ending cursor
// needs to be preserved and we're not working with a one-record span...
if (!f_OneRcrdSpn && us_lenEndPrsrv) {
//get a pointer at which we can virtualize a CDTEXT containing only the
// content to be preserved
if (us_err = us_GetVirtualCdRecAppendPointer( pt_ctx, sizeof( CDTEXT) +
us_lenEndPrsrv, &puc))
return us_err;
//virtualize a CDTEXT based on the ending CDTEXT's format but
// containing just the content not included in the specified span
memcpy( puc, t_crsrEnd.puc_location, sizeof( CDTEXT));
((CDTEXT *) puc)->Header.Length = sizeof( CDTEXT) + us_lenEndPrsrv;
memcpy( puc + sizeof( CDTEXT), t_crsrEnd.puc_location + sizeof(
CDTEXT) + us_offstEnd + 1, us_lenEndPrsrv);
//done with the virtualization of the CDTEXT, update the variable that
// tracks the length of the virtual item being written to
pt_ctx->pt_endVirtual->ul_length += pt_ctx->pt_endVirtual->ul_length %
2 + sizeof( CDTEXT) + us_lenEndPrsrv;
} //if (!f_OneRcrdSpn && us_lenEndPrsrv)
//if the CD record that follows the original ending CD record is
// virtualized...
t_crsr = t_crsrEnd;
AdvanceCdCursor( &t_crsr, pt_ctx, NULL, &f_ItmJustLockd);
if (t_crsr.pt_item && t_crsr.pt_item->i_type == mi_VIRTUAL) {
return !eus_SUCCESS; //PGP development shortcut
//if that CD record is the first record in its item...
//restore virtuality by setting the next pointer of the last item
// in the proxy virtuality equal to the item containing this CD
// record that follows the ending CD record
//else
//virtualize that CD record following the original ending CD record
// and all ensuing records up to the end of its item
//set the next pointer of the last proxy item equal to the item
// pointed to by the next pointer of the item we just virtualized
//else if a following CD record exists (in Actuality)...
}else if (t_crsr.pt_item) {
//reset the actual-frontier absolute offset to the beginning of the CD
// record following the original ending CD record
pt_ctx->ul_ActualFrontier = ul_GetAbsoluteOffset(
t_crsr.puc_location, t_crsr.pt_item,
pt_ctx->pt_Actuality);
//if the item containing the following CD record was just locked in
// memory for the sake of this operation, unlock it now
if (f_ItmJustLockd)
UnlockItem( t_crsr.pt_item);
//else reset the actual-frontier absolute offset to the ultimate length of
// the rich-text field
}else
pt_ctx->ul_ActualFrontier = ul_GetAbsoluteOffset(
t_crsrEnd.puc_location,
t_crsrEnd.pt_item, pt_ctx->pt_Actuality) +
t_crsrEnd.us_recLength +
t_crsrEnd.us_recLength % 2;
//if either the original starting CD record or the CD record following the
// original ending CD record was virtualized...
//if the first item of the proxy virtuality is the same as the original
// item containing the starting CD record...
//discard the items that fall between the original item containing
// the starting CD record and the item pointed to by the next
// pointer in the last proxy-virtual item
//else
//if the original item containing the starting CD record is the
// first virtual item...
//set the virtuality member of the main item-tracking structure
// to point to the first proxy virtual item
//else locate in the original virtuality the item whose next
// pointer specifies this original item and reset its next pointer
// to the first proxy virtual item
//discard the original item and any that follow it up through the
// one pointed to by the next pointer in the last proxy-virtual
// item
return eus_SUCCESS;
} //eus_ReplaceRtfSpanText(
/** us_AppendTextToVirtuality( ***
Purpose is to append a null-terminated buffer of text content to the current
virtual rich-text stream. The procedue does not concern itself with paragraph
styles even though it does break up larg
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -