home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
NOTEPAD2.ZIP
/
MTEXT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-08
|
27KB
|
901 lines
/*
* mtext.c -- Text manager
*
* Created by Microsoft Corporation, 1989
*/
#include <memory.h>
#define INCL_WIN
#include <os2.h>
#include <opendlg.h>
#include "mtypes.h"
#include "mfuncs.h"
/***********************************************************************
* Forward declarations
***********************************************************************/
// update the cursor and anchor position after text change
private VOID UpdateMarks(PED ped, IPT iptFrom, IPT iptTo, IPT cch);
// signal that the text has changed
private VOID TxtSignalChange(PED ped, BOOL fChanged);
/***********************************************************************
* Searching text
***********************************************************************/
/*
* PPR TxtPPROfIpt(PED ped, PIPT ipt)
*
* Given an insertion point, returns a ppr which corresponds to that
* ipt. Note that this could be one of several pieces -- a marker,
* or either of the pieces if an ipt falls in a split between two pieces.
* This function does not guarantee which of those pieces is returned.
*
* As a side-effect, this routine sets sets *pipt to the number of
* characters into the piece at which the ipt will be found.
*
* Note: this function is a preliminary version. It should be rewritten
* for speed.
*/
public PPR TxtPPROfIpt(PED ped, PIPT pipt)
{
if (*pipt >= ped->iptFVL) {
*pipt -= ped->iptFVL;
return(PprOfOffset((PPR)(ped->pmrFVL), pipt));
} else {
return(PprOfOffset(ped->pprHead, pipt));
}
}
/***********************************************************************
* Text Deletion
***********************************************************************/
/*
* PPR DelText(PED ped, IPT offBegin, IPT cch)
*
* Deletes cch characters, starting at offBegin characters into the
* text. Marks marker records as dirty as appropriate.
* Returns the piece containing text immediately before the deleted
* region. Any text that is to be inserted, replacing this deletion,
* can be directly inserted at the end of this returned piece.
* (note that this *will* cause a split at the appropriate
* point even if no text is being deleted.)
*/
private PPR DelText(PED ped, IPT offBegin, IPT cch)
{
PPR ppr;
OFFSET cchDel;
PMR pmr;
ped->iptMac -= cch;
TxtSignalChange(ped, cch>0);
ppr = TxtPPROfIpt(ped, &offBegin);
ppr = SkipMarkers(ppr,MARKER_ANY);
pmr = (PMR)SkipBackText(ppr->pprTextPrev,MARKER_LINE);
pmr->cchValid = min(pmr->cchValid,
TxtLengthToBOLPPR(ped,ppr,(OFFSET)offBegin));
if ((cch + offBegin) < ppr->cchText) {
if (offBegin > 0) {
ppr = SplitPiece(ped, ppr, (SHORT)offBegin);
}
ppr = DelStartChars(ped, ppr, (SHORT)cch);
} else {
if (cch > 0) {
cchDel = (OFFSET)min((IPT)PieceLength(ppr)-offBegin,cch);
ppr = DelEndChars(ped, ppr, cchDel);
cch -= cchDel;
while (cch > 0) {
cchDel = (OFFSET)min((IPT)PieceLength(ppr),cch);
ppr = DelStartChars(ped, ppr, cchDel);
cch -= cchDel;
}
}
}
return(ppr->pprTextPrev);
}
/***********************************************************************
* Text Insertion
***********************************************************************/
/*
* BOOL InsText(PED ped, PPR ppr, PCHAR pchFrom, OFFSET cch)
*
* Inserts cch characters from *pchFrom at the end of the piece ppr.
* Returns TRUE iff the insertion finished successfully.
*/
private BOOL InsText(PED ped, PPR ppr, PCHAR pchFrom, OFFSET cch)
{
OFFSET cchRes, cchToGo;
PCHAR pchTo;
BOOL fOkay;
if (cch == 0)
return(TRUE);
TxtSignalChange(ped, TRUE);
fOkay = TRUE;
cchToGo = cch;
while (cchToGo > 0) {
cchRes = cchToGo;
pchTo = InsEndChars(ped, &ppr, &cchRes);
if (pchTo == NULL) { // memory failure
NotifyOwner(ped, EN_MEMERROR, NULL);
fOkay = FALSE;
break;
}
LCopyStruct(pchFrom, pchTo, cchRes);
cchToGo -= cchRes;
pchFrom += cchRes;
}
ped->iptMac += cch;
return(fOkay);
}
/***********************************************************************
* Text reformatting
***********************************************************************/
/*
* VOID SetValidPt(PMR pmr)
*
* Sets the valid point to be at most the current pixel/character length.
*/
private VOID SetValidPt(PMR pmr)
{
if (pmr->cchValid >= pmr->cchLine) {
pmr->cchValid = pmr->cchLine;
pmr->pixValid = pmr->pixLine;
}
}
/*
* VOID TxtReformatNoWW(PED ped, PPR ppr, BOOL fAllText)
*
* A change has been made which affects the text; the text needs
* to be reformatted as a result. This change could either be that text
* has been inserted or deleted, or that the formatting size has changed.
* All characters up to the piece PPR are assumed to be
* correctly formatted for the current formatting status.
* All bets are off after that ipt -- the text can be wrongly
* formatted; the text can contain any text, including end-of-line
* markers (which will require inserting new line markers.)
*
* if fAllText == TRUE, then we are trying to reformat the entire text
* from beginning to end.
*
* This function is used only when reformatting with word-wrap off.
*/
public VOID TxtReformatNoWW(PED ped, PPR ppr, BOOL fAllText)
{
OFFSET off;
register CHAR ch;
PMR pmrLine;
BOOL fExit;
PPR pprSave;
// set ppr to be the beginning of line's text (if not already) and
// set beginning-of-line piece pointer
pmrLine = (PMR)SkipBackText(ppr,MARKER_LINE);
ppr = SkipMarkers(pmrLine->pr.pprTextNext,~MARKER_LINE);
// miscellaneous initialisation
pmrLine->pixLine = 0;
pmrLine->cchLine = 0;
off = 0;
ch = CharOfPointer(ppr,off);
fExit = FALSE;
while (!fExit) {
if (pmrLine->cchValid == pmrLine->cchLine)
SetValidPt(pmrLine);
if (fIsMarker(ppr)) {
if (((PMR)ppr)->fFlags & MARKER_EOT) {
fExit = TRUE;
if (pmrLine->pixLine > ped->pixCurMax)
ped->pixCurMax = pmrLine->pixLine;
SetValidPt(pmrLine);
} else {
pprSave = ppr;
ch = AdvancePointer(&ppr, &off);
DelMarker(ped, (PMR)pprSave);
SetValidPt(pmrLine);
}
} else {
if (ch == '\n') {
pmrLine->cchLine++;
if (pmrLine->pixLine > ped->pixCurMax)
ped->pixCurMax = pmrLine->pixLine;
SetValidPt(pmrLine);
ch = AdvancePointer(&ppr, &off);
ppr = ConditionalSplitPiece(ped,ppr,off);
off = 0;
if (fIsMarkerType(ppr,(MARKER_LB))) {
fExit = !fAllText;
if (fExit) {
break;
}
pmrLine = (PMR)ppr;
ch = AdvancePointer(&ppr, &off);
} else {
pmrLine = InsBeforeMarker(ped,ppr,MARKER_LB);
}
pmrLine->pixLine = 0;
pmrLine->cchLine = 0;
} else {
if (fAllText && (ch == '\t')) {
SetValidPt(pmrLine);
}
pmrLine->cchLine++;
pmrLine->pixLine += PixOfChar(ped,
pmrLine->pixLine,
ch);
ch = AdvancePointer(&ppr, &off);
}
}
}
}
/*
* VOID TxtReformatWW(PED ped, PPR ppr, BOOL fAllText)
*
* A change has been made which affects the text; the text needs
* to be reformatted as a result. This change could either be that text
* has been inserted or deleted, or that the formatting size has changed.
* All characters up to the piece PPR are assumed to be
* correctly formatted for the current formatting status (i.e. are word
* wrapped according to current window dimensions and no textual change
* has been made.) All bets are off after that ipt -- the text can be wrongly
* formatted; the text can contain any text, including end-of-line
* markers (which will require inserting new line markers.) Note that
* deleting spaces may cause characters to be moved to the previous line.
*
* if fAllText == TRUE, then we are trying to reformat the entire text
* from beginning to end.
*
* This function is used only when reformatting with word-wrap on.
*/
public VOID TxtReformatWW(PED ped, PPR ppr, BOOL fAllText)
{
PIX pix, pixLine, pixLineSave;
IPT cchLineSave;
OFFSET off, offSave;
BOOL fExit;
PPR pprSave;
BOOL fFirstOnLine;
register CHAR ch;
IPT cMarkers;
PMR pmrLine;
// set ppr to be the beginning of the previous line's text (if any)
ppr = SkipBackText(ppr,MARKER_LINE);
cMarkers = 1;
if (ppr->pprTextPrev != NULL) {
cMarkers = 0;
ppr = ppr->pprTextPrev;
ppr = SkipBackText(ppr,MARKER_LINE);
}
pmrLine = (PMR)ppr;
ppr = SkipMarkers(ppr,MARKER_ANY);
// miscellaneous initialisation
pixLine = 0;
pmrLine->pixLine = 0;
pmrLine->cchLine = 0;
off = 0;
fFirstOnLine = TRUE;
for (fExit = FALSE; !fExit; ) {
if (fIsMarker(ppr)) {
if (((PMR)ppr)->fFlags & MARKER_EOT) {
fExit = TRUE;
} else {
pprSave = ppr;
ppr = ppr->pprTextNext;
off = 0;
DelMarker(ped, (PMR)pprSave);
cMarkers++;
pmrLine->cchValid = min(pmrLine->cchValid,pmrLine->cchLine);
}
} else {
ch = *(ppr->pchText + off);
while (fFirstOnLine && !(fIsWhiteSpace(ch)) && (ch != '\n') && !(fIsMarker(ppr))) {
pix = PixOfChar(ped,pixLine,ch);
pixLine += pix;
pmrLine->pixLine += pix;
pmrLine->cchLine++;
pprSave = ppr;
offSave = off;
pixLineSave = pixLine;
cchLineSave = pmrLine->cchLine;
ch = AdvancePointer(&ppr, &off);
if (fIsWhiteSpace(ch) || (ch == '\n')) {
fFirstOnLine = FALSE;
break;
} else if ((pixLine>DispWidth(ped)) && (ped->fWordWrap)) {
ppr = ConditionalSplitPiece(ped, pprSave, offSave);
pmrLine->cchLine = cchLineSave;
pmrLine->pixLine = pixLineSave;
pmrLine = InsBeforeMarker(ped,ppr,MARKER_SPILL);
ppr = pprSave;
off = offSave;
fFirstOnLine = TRUE;
pixLine = 0;
pmrLine->pixLine = 0;
pmrLine->cchLine = 0;
}
}
while (!fIsMarker(ppr)) {
while ((ch == ' ') || (ch == '\t')) {
fFirstOnLine = FALSE;
pix = PixOfChar(ped,pixLine,ch);
pixLine += pix;
pmrLine->pixLine += pix;
pmrLine->cchLine++;
ch = AdvancePointer(&ppr, &off);
}
if (ch == '\n') {
pmrLine->cchLine++;
ch = AdvancePointer(&ppr, &off);
ppr = ConditionalSplitPiece(ped, ppr, off);
off = 0;
if (fIsMarkerType(ppr,MARKER_LB) && !fAllText) {
if ((cMarkers > 0) && (!fAllText)) {
fExit = TRUE;
} else {
pmrLine = (PMR)ppr;
cMarkers++;
AdvancePointer(&ppr, &off);
}
} else {
pmrLine = InsBeforeMarker(ped,ppr,MARKER_LB);
}
if (pixLine > ped->pixCurMax)
ped->pixCurMax = pixLine;
fFirstOnLine = TRUE;
pixLine = 0;
if (!fExit) {
pmrLine->pixLine = 0;
pmrLine->cchLine = 0;
}
break;
}
if (!fIsWhiteSpace(ch) && !fIsMarker(ppr)) {
pprSave = ppr;
offSave = off;
pixLineSave = pixLine;
cchLineSave = pmrLine->cchLine;
do {
pix = PixOfChar(ped,pixLine,ch);
pixLine += pix;
pmrLine->pixLine += pix;
pmrLine->cchLine++;
ch = AdvancePointer(&ppr, &off);
} while (!fIsWhiteSpace(ch) &&
(ch != '\n') &&
((!ped->fWordWrap)||(pixLine <= DispWidth(ped))) &&
!fIsMarker(ppr));
if ((!ped->fWordWrap) && (pixLine > DispWidth(ped))) {
ppr = pprSave;
off = offSave;
pmrLine->pixLine = pixLineSave;
pmrLine->cchLine = cchLineSave;
ch = '\0';
ppr = ConditionalSplitPiece(ped, ppr, off);
off = 0;
pmrLine = InsBeforeMarker(ped,ppr,MARKER_SLB);
fFirstOnLine = TRUE;
if (pixLine > ped->pixCurMax)
ped->pixCurMax = pixLine;
pixLine = 0;
pmrLine->pixLine = 0;
pmrLine->cchLine = 0;
break;
}
}
}
}
}
}
/*
* VOID TxtReformat(PED ped, PPR ppr, BOOL fAllText)
*
* A change has been made which affects the text; the text needs
* to be reformatted as a result. This change could either be that text
* has been inserted or deleted, or that the formatting size has changed.
* All characters up to the piece PPR are assumed to be
* correctly formatted for the current formatting status (i.e. are word
* wrapped according to current window dimensions and no textual change
* has been made.) All bets are off after that ipt -- the text can be wrongly
* formatted; the text can contain any text, including end-of-line
* markers (which will require inserting new line markers.) Note that
* deleting spaces may cause characters to be moved to the previous line.
*
* if fAllText == TRUE, then we are trying to reformat the entire text
* from beginning to end.
*/
public VOID TxtReformat(PED ped, PPR ppr, BOOL fAllText)
{
if (TxtQueryWordWrap(ped)) {
TxtReformatWW(ped, ppr, fAllText);
} else {
TxtReformatNoWW(ped, ppr, fAllText);
}
}
/***********************************************************************
* Really truly global functions
* These functions define the interface to the outside world
***********************************************************************/
/*
* BOOL TxtInit(PED ped)
*
* Initialises the text manager by creating a single empty paragraph.
* Assumes memory manager has already been initialised. Causes
* initialisation of piece manager.
*
* Returns TRUE iff initialisation went through without a problem.
*/
public BOOL TxtInit(PED ped)
{
PPR ppr;
ped->iptCursor = ped->iptAnchor = 0L;
ppr = PieceInit(ped,CCHDEFAULTMAX);
ped->pprHead = (PPR)InsBeforeMarker(ped, ppr, MARKER_BOT);
LockMarker((PMR)ped->pprHead,TRUE);
ped->pprTail = (PPR)InsEndMarker(ped, ppr, MARKER_EOT);
LockMarker((PMR)ped->pprTail,TRUE);
ped->fWordWrap = FALSE;
ped->fChanged = FALSE;
ped->iptMac = 0;
ped->iptMax = CCHDEFAULTMAX;
return(ped->pprHead != NULL);
}
/*
* BOOL TxtChange(PED ped, IPT iptFrom, IPT iptTo, PCHAR pch, IPT cch)
*
* Causes the text in the range [from, to) to be deleted, and replaced
* with the contents of the buffer pointed to by pch. The buffer is
* assumed to be cch characters long. Note that buffers are limited
* to 64K-1 bytes in length.
*
* If a maximum text length has been defined, and the change will cause
* the text length to exceed that limit, the change fails and no changes
* are made.
*
* Initiates a reformat on the text.
* Returns true iff the operation completed successfully.
*/
public BOOL TxtChange(PED ped, IPT iptFrom, IPT iptTo, PCHAR pch, OFFSET cch)
{
PPR ppr;
IPT iptRem;
if (iptTo < iptFrom) {
iptRem = iptTo;
iptTo = iptFrom;
iptFrom = iptRem;
}
if ((ped->iptMax>0) && (ped->iptMac+cch-iptTo+iptFrom>ped->iptMax)) {
NotifyOwner(ped, EN_MEMERROR, NULL);
return(FALSE);
}
ppr = DelText(ped, iptFrom, iptTo-iptFrom);
if (!InsText(ped, ppr, pch, cch)) {
return(FALSE);
}
TxtReformat(ped, ppr, FALSE);
UpdateMarks(ped, iptFrom, iptTo, (IPT)cch);
return(TRUE);
}
/*
* IPT TxtLength(PED ped)
*
* returns the total number of characters in the text.
*/
public IPT TxtLength(PED ped)
{
return(ped->iptMac);
}
/***********************************************************************
* Word wrap status
***********************************************************************/
/*
* BOOL TxtQueryWordWrap(PED ped)
*
* Returns the word wrap status of a document.
*/
public BOOL TxtQueryWordWrap(PED ped)
{
return(ped->fWordWrap);
}
/*
* BOOL TxtSetWordWrap(PED ped, BOOL fWW)
*
* Sets a document's wordwrap status to fWW.
* Causes reformatting to occur if wordwrap is being turned on.
*/
public BOOL TxtSetWordWrap(PED ped, BOOL fWW)
{
if (fWW != ped->fWordWrap) {
ped->fWordWrap = fWW;
TxtReformat(ped, ped->pprHead, TRUE);
}
return(fWW);
}
/***********************************************************************
* Cursor/Anchor external manipulation
***********************************************************************/
/*
* IPT UpdateAMark(IPT ipt, IPT iptFrom, IPT iptTo, IPT cch, BOOL fEnd)
*
* Given a TxtChange which deleted the range iptFrom..iptTo and replaced
* it with cch characters at iptFrom, updates the mark ipt to reflect
* the deletion/insertion. fEnd => mark will be set to end of changed
* region if mark was in [iptFrom, iptTo], else will be set to beginning
* of changed region.
*/
private IPT UpdateAMark(IPT ipt, IPT iptFrom, IPT iptTo, IPT cch, BOOL fEnd)
{
if (ipt >= iptFrom) {
if (ipt <= iptTo) {
ipt = iptFrom + (fEnd ? cch : 0);
} else {
ipt += cch - iptTo + iptFrom;
}
}
return(ipt);
}
/*
* VOID UpdateMarks(PED ped, IPT iptFrom, IPT iptTo, IPT cch)
*
* Given a TxtChange which deleted the range iptFrom..iptTo and replaced
* it with cch characters at iptFrom, updates the marks to reflect
* the deletion/insertion.
*/
private VOID UpdateMarks(PED ped, IPT iptFrom, IPT iptTo, IPT cch)
{
TxtSetAnchorCursor(ped,
UpdateAMark(ped->iptAnchor, iptFrom, iptTo, cch, TRUE),
UpdateAMark(ped->iptCursor, iptFrom, iptTo, cch, TRUE));
ped->iptFVL = UpdateAMark(ped->iptFVL, iptFrom, iptTo, cch, FALSE);
}
/*
* IPT TxtQueryAnchor(PED ped)
*
* Returns the current anchor.
*/
public IPT TxtQueryAnchor(PED ped)
{
return(ped->iptAnchor);
}
/*
* IPT TxtQueryCursor(PED ped)
*
* Returns the current cursor.
*/
public IPT TxtQueryCursor(PED ped)
{
return(ped->iptCursor);
}
/*
* IPT TxtQueryMinSel(PED ped)
*
* Returns the current minimum selection point.
*/
public IPT TxtQueryMinSel(PED ped)
{
return((ped->iptAnchor<ped->iptCursor)?ped->iptAnchor:ped->iptCursor);
}
/*
* IPT TxtQueryMaxSel(PED ped)
*
* Returns the current maximum selection point.
*/
public IPT TxtQueryMaxSel(PED ped)
{
return((ped->iptAnchor>ped->iptCursor)?ped->iptAnchor:ped->iptCursor);
}
/*
* BOOL TxtSetAnchorCursor(PED ped, IPT iptAnchor, IPT iptCursor)
*
* Sets the cursor and anchor position. Does not cause redraw.
* If an ipt is negative, leaves that mark alone.
*/
public IPT TxtSetAnchorCursor(PED ped, IPT iptAnchor, IPT iptCursor)
{
IPT cchText;
cchText = TxtLength(ped);
ped->fSelDelta = TRUE;
if (iptAnchor >= 0)
ped->iptAnchor = min(cchText,iptAnchor);
if (iptCursor >= 0)
ped->iptCursor = min(cchText,iptCursor);
return(TRUE);
}
/***********************************************************************
* Changed flag status
***********************************************************************/
/*
* BOOL TxtQueryChanged(PED ped)
*
* Returns the changed status of a document.
*/
public BOOL TxtQueryChanged(PED ped)
{
return(ped->fChanged);
}
/*
* BOOL TxtSetChanged(PED ped, BOOL fChanged)
*
* Sets a document's wordwrap status to fChanged. Returns old changed status.
*/
public BOOL TxtSetChanged(PED ped, BOOL fChanged)
{
if (fChanged != ped->fChanged) {
ped->fChanged = fChanged;
if (fChanged) {
NotifyOwner(ped, EN_CHANGE, NULL);
return(FALSE);
} else {
return(TRUE);
}
} else {
return(fChanged);
}
}
/*
* VOID TxtSignalChange(PED ped, BOOL fChanged)
*
* Signals that a change has happened if fChanged is TRUE.
*/
private VOID TxtSignalChange(PED ped, BOOL fChanged)
{
if (fChanged)
TxtSetChanged(ped,TRUE);
}
/***********************************************************************
* Text Limit Set/Query
***********************************************************************/
/*
* IPT TxtQueryLimit(PED ped)
*
* Returns the maximum text length of a document.
*/
public IPT TxtQueryLimit(PED ped)
{
return(ped->iptMax);
}
/*
* BOOL TxtSetLimit(PED ped, IPT iptMax)
*
* Sets the text limit to a given value. If more text than the new
* limit currently exists, truncates the document. Returns TRUE if
* the limit was set without truncation; FALSE otherwise.
*/
public BOOL TxtSetLimit(PED ped, IPT iptMax)
{
ped->iptMax = iptMax;
if ((ped->iptMac > iptMax) && (iptMax > 0)) {
TxtChange(ped, iptMax, ped->iptMac, NULL, 0);
return(FALSE);
} else {
return(TRUE);
}
}
/***********************************************************************
* Miscellaneous text structure queries
***********************************************************************/
/*
* IPT TxtLengthToEOLPPR(PED ped, PPR ppr, OFFSET off, BOOL fIncludeLBCh)
*
* Returns the number of characters between this ppr/off and the end of
* the line. Only valid in formatted text.
*/
public IPT TxtLengthToEOLPPR(PED ped, PPR ppr, OFFSET off, BOOL fIncludeLBCh)
{
IPT cipt;
cipt = -off;
if (!ped) return cipt;
do {
cipt += ppr->cchText;
ppr = ppr->pprTextNext;
} while ((ppr != NULL) &&
(!fIsMarker(ppr) || !(((PMR)ppr)->fFlags & MARKER_LINE)));
if (!fIncludeLBCh &&
(ppr != NULL) &&
(((PMR)ppr)->fFlags & MARKER_LB))
cipt--;
return(cipt);
}
/*
* IPT TxtLengthToEOL(PED ped, IPT ipt, BOOL fIncludeLBCh)
*
* Returns the number of characters between this ipt and the end of
* the line. Only valid in formatted text.
*/
public IPT TxtLengthToEOL(PED ped, IPT ipt, BOOL fIncludeLBCh)
{
PPR ppr;
ppr = TxtPPROfIpt(ped, &ipt);
return(TxtLengthToEOLPPR(ped, ppr, (OFFSET)ipt, fIncludeLBCh));
}
/*
* IPT TxtLengthToBOLPPR(PED ped, PPR ppr, OFFSET off)
*
* Returns the number of characters between this ppr/off and the beginning of
* the line. Only valid in formatted text.
*/
public IPT TxtLengthToBOLPPR(PED ped, PPR ppr, OFFSET off)
{
IPT cipt;
cipt = off;
if (!ped) return cipt;
ppr = ppr->pprTextPrev;
while ((ppr != NULL) &&
(!fIsMarker(ppr) || !(((PMR)ppr)->fFlags & MARKER_LINE))) {
cipt += ppr->cchText;
ppr = ppr->pprTextPrev;
}
return(cipt);
}
/*
* IPT TxtLengthToBOL(PED ped, IPT ipt)
*
* Returns the number of characters between this ipt and the beginning of
* the line. Only valid in formatted text.
*/
public IPT TxtLengthToBOL(PED ped, IPT ipt)
{
PPR ppr;
ppr = TxtPPROfIpt(ped, &ipt);
return(TxtLengthToBOLPPR(ped, ppr, (OFFSET)ipt));
}
/*
* IPT TxtLineLength(PED ped, PPR ppr)
*
* Returns the length of a line containing a piece.
*/
public IPT TxtLineLength(PED ped, PPR ppr)
{
IPT cipt;
cipt = 0;
ppr = SkipBackText(ppr, MARKER_LINE);
return(TxtLengthToEOLPPR(ped, ppr, 0, TRUE));
}
/*
* IPT TxtCchToBegOfToken(PPR ppr, OFFSET off)
*
* Returns the number of characters between this ppr/off and the beginning of
* the surrounding token.
*/
public IPT TxtCchToBegOfToken(PPR ppr, OFFSET off)
{
BOOL fSpace;
CHAR ch;
IPT cch = 0;
if (fIsMarker(ppr)) {
ppr = SkipMarkers(ppr, MARKER_ANY);
off = 0;
}
ch = CharOfPointer(ppr, off);
fSpace = fIsWhiteSpace(ch);
while ((fIsWhiteSpace(ch) == fSpace) && (ch != '\n')) {
cch++;
do {
ch = RetreatPointer(&ppr, &off);
} while (fIsMarkerType(ppr,MARKER_NOTLINE));
if (fIsMarker(ppr)) {
return(cch-1);
}
}
return(cch-1);
}
/*
* IPT TxtCchToEndOfToken(PPR ppr, OFFSET off)
*
* Returns the number of characters between this ppr/off and the end of
* the surrounding token. If ppr is a marker, uses next piece.
*/
public IPT TxtCchToEndOfToken(PPR ppr, OFFSET off)
{
BOOL fSpace;
CHAR ch;
IPT cch = 0;
if (fIsMarker(ppr)) {
ppr = SkipMarkers(ppr, MARKER_ANY);
off = 0;
}
ch = CharOfPointer(ppr, off);
fSpace = fIsWhiteSpace(ch);
while ((fIsWhiteSpace(ch) == fSpace) && (ch != '\n')) {
cch++;
do {
ch = AdvancePointer(&ppr, &off);
} while (fIsMarker(ppr) && (((PMR)ppr)->fFlags & (~MARKER_LINE)));
if (fIsMarker(ppr)) {
break;
}
}
return(cch);
}