📄 richtexthandling.c
字号:
/*______________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: RichTextHandling.c,v 1.11 2002/09/09 00:31:43 sdas Exp $
______________________________________________________________________________*/
/*::: MODULE OVERVIEW :::::::::::::
Purpose is to encapsulate low-level functionality for handling Notes
rich-text. To use this functionality, the developer should include the
LibRichText.h header file in her own module.
--- suggested enhancements ---
11/10/98 PR
+ Decouple the rich-text item information members in the ItemInfo structure
from the linked-list implementation of stringing such items together.
My suggested approach is to create a new structure called something like
ItemNode that has two members: an ItemInfo structure and a pointer to
the next ItemNode in the list.
+ A currently un-addressed problem in this implementation is that the content
of rich-text items become locked in memory for access purposes. However
the items are never then unlocked until the rich-text field is discarded.
This is wasteful of memory resources. My suggested solution is to
implement a mechanism for saving and restoring state information about
the memory locks on rich-text content associated with a given rich-text
context. An idea of the direction I would take can be gleaned from the
sidelined commentary in the f_TestStringStart() function and in the
corresponding, currently unused MemLockStateInfo structure defined in the
RichTextHandling.h header file. Such a mechanism would provide internal,
and possibly external, logic a simple means with which to conserve memory
resources.
11/26/98 PR
Perhaps some reference-count locking mechanism should be incorporated into
the ItemInfo structure so that items can be locked and "unlocked" freely with
no risk of invalidating unknown pointers which rely on the formerly locked
item information. The current set-up poses some risks. See the in-line
documentation in us_VirtualAppend() for a real example of a risk being taken
which could be avoided if we had some reference-count mechanism.
I wonder... Does OSLockBlock() and OSUnlockBlock() already provide us with
a refrence-count mechanism that we could utilize?
11/30/98 PR
The current implementation of "absolute offsets," including ActualFrontier,
include the length of the TYPE_COMPOSITE beginning to rich-text items. Better
to make absolute offsets completely independent of the item structure against
which the offset is to be measured.
11/30/98 PR
Based on the logic specified in eus_ReplaceRtfSpanText(), we may be able to
simplify matters by getting rid of semi-virtuality altogether. Since
virtuality can always be adjusted with little performance hit if the
adjustments are made only at the end of an item, there seems to be little
need for a semi-virtuality that is little more than a mechanism for adjusting
virtualized content at the end of virtuality.
12/8/98 PR: comment
But semi-virtuality may still be useful for streaming CD records together
without having to worry about item limits -- ad-hoc buffers, for example?
I don't really like allocating a full segment if all I need is some space
to string a few CD records together. But then again, I want to isolate
this module and allow it to be accessible from a higher level, meaning
that I have to give up some efficiency & fine-tuning possibilities.
3/20/00 PR: comment
I am becoming convinced that doing away with semi-virtuality in favor of
substantially extending support for ad-hoc buffers. It would be useful,
for instance, to be able to write _ad-hoc_ to a pre-allocated buffer for
a CD-record stream, and then be able to copy/append/insert such a buffer
into a specified virtuality context. This functionality would fit nicely
into the eus_InsertSubformTop() procedure, for example, with respect to
its need to write a particular text-structure more than once.
3/20/00 PR: The NSFItemConvertToText and NSFItemConvertValueToText APIs might
be a much simpler way to extract text from rich-text items than what's
currently implemented here. Much testing is required to find out:
end-of-line handling and hotspot-text handling, for prime examples.
--- revision history ---------
9/6/02 Version 1.2 Paul Ryan
+ added eus_CursorAdvance(), eus_InsertAttachHotspot()
+ enhanced eus_ReplaceRtfSpanText() so it outputs rich-text span marking
replacement
+ improved reliability of ef_CursorToAttachmentHotspot()
+ improved eus_WriteEndHotspotRecord() causing rename to eus_InsertHotspotEnd()
+ fixed bug in f_TestStringStart()
+ added documentation, generally improved consisting of code and listing format
11/14/00 Version 1.1.6: Paul Ryan
+ documentation adjustment
9/16/00 Version 1.1.5 Paul Ryan
+ finished enhancements surrounding special handling of PGP-encoded
attachments in a Notes message
+ minor output adjustment made to ef_CursorToAttachmentHotspot()
+ documentation improvement
8/9/00 Version 1.1.4
+ began enhancements surrounding special handling of PGP-encoded attachments
in a Notes message
+ minor logic adjustments
5/30/00 Version 1.1.3 Paul Ryan
+ documentation improvement
3/20/00 Version 1.1.2 Paul Ryan
+ adjustment of eus_InsertSubformTop() to allow subforms consisting of
multiple rich-text items to be inserted correctly
+ adjustments made in support of making the PGP Plug-In compatible with the
Notes R5 mail template
+ enhancements to handling of the rich-text-field information structure
+ improved initial-context checking in us_CompileActuality() such that
procedure fails if specified item is not in fact a rich-text field
+ Extended us_VirtualizeRestOfRtf() such that the target virtuality does not
have to belong to the rich-text context structure holding the source
actuality. The extenstion caused the signature of eus_InsertSubformTop()
to change as well.
+ improvement to span-alignment output of ef_CursorToAttachmentHotspot()
+ factored out functionality for locating the hotspot-end CD record
corresponding to a provided hotspot-begin record: f_CursorToHotspotEnd()
+ bug fix to eus_AppendAttachmentHotspot()
+ enhanced fault-tolerance in stepping through rich-text streams, adjusting
AdvanceCdCursor() and generating f_PushToNextItem()
+ added and leveraged throughout the utility procedure UnlockItem()
+ much documentation improvement
9/12/99 Version 1.1 Paul Ryan
+ fixed bugs in eus_ReplaceRtfWithStandardText() so that messages exceeding
64K are handled properly
+ Enhanced eus_ReplaceRtfSpanText() to handle translation of PGP ASCII-Armor
blocks greaer than 64K in size. Process led to creation of
us_AppendTextToVirtuality() and concomitant adjustment of
eus_ReplaceRtfWithStandardText().
1/16/99 Version 1.0 Paul Ryan
::::::::::::::::::::::::::::::::::::*/
#include "RichTextHandling.h"
const BOOL ei_FOREVER = TRUE;
const DWORD eul_ERR_FAILURE = 0xFFFFFFFF; //function failure code for
// eul_GetTextSpanText(), etc.
#define muc_SIGTYPE_LSIG '\0'
#define muc_SIGTYPE_WSIG (BYTE) '\xFF' //for some reason '\xFF' by itself
// produces a maxed-out 'int', all F's
static const BYTE muc_SIG_CDTEXT = LOBYTE( SIG_CD_TEXT);
#ifndef SIG_CD_BEGIN //ensure that we can understand
// certain critical R5 CD structures no matter what version
// of the Notes C API we're compiling with
#define SIG_CD_BEGIN (221 | BYTERECORDLENGTH)
#define SIG_CD_END (222 | BYTERECORDLENGTH)
typedef struct {
BSIG Header; /* Signature and length of this record */
WORD Version;
WORD Signature; /* Signature of record begin is for */
} CDBEGINRECORD;
typedef struct {
BSIG Header; /* Signature and length of this record */
WORD Version;
WORD Signature; /* Signature of record end is for */
} CDENDRECORD;
#endif //ndef SIG_CD_BEGIN
static const char mc_LINEFEED_RICHTEXT = '\0';
static const DWORD mul_MAXLEN_RICH_TEXT_ITEM = MAXONESEGSIZE,
mul_COMFY_LIMIT = 0x0400 * 40,
mul_STRETCH_LIMIT = 0x0400 * 55,
mul_FRONTIER_NO_MORE = 0xFFFFFFFF;
static const WORD mus_MAX_STYLE_ID = 0xFFFF,
mus_LENLIMIT_CDTEXT_REC = 20 * 0x400;
static const CDHOTSPOTEND mt_HOTSPOT_END = {{SIG_CD_HOTSPOTEND,
sizeof( CDHOTSPOTEND)}};
static const CDPARAGRAPH mt_PARAGRAPH = {{SIG_CD_PARAGRAPH,
sizeof( CDPARAGRAPH)}};
static const CDBEGINRECORD mt_R5_BEGIN_HOTSPOT = {{SIG_CD_BEGIN,
sizeof( CDBEGINRECORD)}, 0,
SIG_CD_V4HOTSPOTBEGIN};
static const CDENDRECORD mt_R5_END_HOTSPOT = {{SIG_CD_END,
sizeof( CDENDRECORD)}, 0,
SIG_CD_V4HOTSPOTEND};
static const CDHOTSPOTEND mt_V4HOTSPOT_END = {{SIG_CD_V4HOTSPOTEND,
sizeof( CDHOTSPOTEND)}};
/** eus_InitializeRtfContext( ***
Purpose is to initialize a rich-text-field context structure the caller needs
to use to employ the functionality of this module for handling Lotus Notes
rich text. The caller chooses whether to engage a complete initialization
based on an existing field or to simply initialize a context with which
free-form rich-text content may be constructed. The caller is responsible for
disposal of the resources tracked by the rich-text context structure, via a
call to ef_FreeRtfContext().
--- parameters & return ----
h_NOTE: handle to the open note containing the rich-text field which should
be described by this procedure
pc_ITMNM: pointer to the string telling the name of the rich-text field to be
described by this procedure
pt_cursor: Optional Output. Pointer to the variable in which to store a
rich-text cursor pointing to the first CD record in the rich-text field
to be manipulated. Ignored if passed in null.
pt_context: Output. Pointer to the context structure to be initialized to
describe the specified field. This context structure is required input to
most of the public interfaces to this module and so must be maintained by
the calling procedure.
RETURN: eus_SUCCESS if no error occured. !eus_SUCCESS if any parameters are
invalid. The Notes API error code otherwise. The procedure will always
be successful if the context structure is not being initialized to
describe an existing rich-text field.
--- revision history -------
3/20/00 PR: documentation improvement
2/11/99 PR: created */
STATUS eus_InitializeRtfContext( NOTEHANDLE h_NOTE,
char pc_ITMNM[],
CdRecordCursor *const pt_cursor,
RtfTrackingInfo *const pt_context) {
ItemInfo * pt_item, * pt_itm;
UINT ui_blankItems = NULL;
STATUS us_err;
BOOL f_failure = FALSE;
if (!( h_NOTE && pc_ITMNM && pt_context))
return !eus_SUCCESS;
memset( pt_context, NULL, sizeof( RtfTrackingInfo));
if (pt_cursor)
memset( pt_cursor, NULL, sizeof( CdRecordCursor));
//Fill out the context's Actuality list. If the specified rich-text field
// doesn't exist, short-circuit with success.
if (us_err = us_CompileActuality( h_NOTE, pc_ITMNM, &pt_item))
return us_err;
if (!pt_item)
return eus_SUCCESS;
//initialize the cursor to point to the beginning of the first rich-text
// item's content
if (pt_cursor)
if (!f_ConstructStartCursor( NULL, pt_item, pt_cursor, NULL))
goto errJump;
pt_itm = pt_item;
while (pt_itm->ul_length == sizeof( WORD)) {
ui_blankItems++;
if (!( pt_itm = pt_itm->pt_next))
goto errJump;
}
pt_context->pt_Actuality = pt_item;
pt_context->ul_ActualFrontier = sizeof( WORD) * (ui_blankItems + 1);
return eus_SUCCESS;
errJump:
ClearItemList( &pt_item);
return !eus_SUCCESS;
} //eus_InitializeRtfContext(
/** eus_ActionHotspotJustBefore( ***
Tells whether a begin-action-hotspot CD record immediately precedes the CD
record pointed to by caller.
--- parameters & return ----
pt_CRSR: address of structure telling the location of the CD record whose
predecessor if of interest
pt_CTX: address of structure describing the the rich-text environment we're
operating with
pf: Output. Address of flag variable in which to store whether a
begin-action-hotspot precedes (TRUE) or not (FALSE).
RETURN:
eus_ERR_INVLD_ARG if any passed-in parameter is obviously invalid
eus_SUCCESS if no error occured
Notes API error code otherwise
--- revision history -------
9/6/02 PR: created */
STATUS eus_ActionHotspotJustBefore( const CdRecordCursor *const pt_CRSR,
const RtfTrackingInfo *const pt_CTX,
BOOL *const pf) {
CdRecordCursor t_crsr;
BOOL f_itmLockd;
CDHOTSPOTBEGIN * pt;
STATUS us_err;
if (!( pt_CRSR && pt_CRSR->puc_location && pt_CRSR->pt_item && pt_CTX &&
pf))
return eus_ERR_INVLD_ARG;
*pf = FALSE;
//if the immediately previous CD record is the start of an action hotspot,
// tell caller so
t_crsr = *pt_CRSR;
if (us_err = us_RetreatCursor( &t_crsr, pt_CTX, &f_itmLockd))
return us_err;
if (*t_crsr.puc_location == LOBYTE( SIG_CD_V4HOTSPOTBEGIN) &&
(pt = (CDHOTSPOTBEGIN *) t_crsr.puc_location)->Type ==
HOTSPOTREC_TYPE_HOTREGION && pt->Flags &
HOTSPOTREC_RUNFLAG_BEGIN && pt->Flags &
HOTSPOTREC_RUNFLAG_ACTION | HOTSPOTREC_RUNFLAG_SCRIPT |
HOTSPOTREC_RUNFLAG_FORMULA)
*pf = TRUE;
//if necessary, put memory resources back the way they were
if (f_itmLockd)
UnlockItem( t_crsr.pt_item);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -