eudora-mac/Editor/Source/Editor Source/getputstyles.c

1 line
40 KiB
C
Executable File

/* Copyright (c) 2017, Computer History Museum
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to
the limitations in the disclaimer below) provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. */
#include "petepch.h"
void FlushStyleRunCache(ParagraphInfoHandle paraInfo)
{
(**paraInfo).styleRunCacheIndex = 0L;
(**paraInfo).styleRunCacheOffset = 0L;
}
long CountStyleRuns(ParagraphInfoHandle paraInfo)
{
return ((InlineGetHandleSize((Handle)paraInfo) - (offsetof(ParagraphInfo, tabStops) + (ABS((**paraInfo).tabCount) * sizeof(short)))) / sizeof(LongStyleRun)) - 1L;
}
/* Get the style run record. This will be fancier, reading off the disk, later */
long GetStyleRun(LongStyleRunPtr theStyleRun, ParagraphInfoHandle paraInfo, long styleRunIndex)
{
LongStyleRunPtr styleRunPtr;
styleRunPtr = (LongStyleRunPtr)&(**paraInfo).tabStops[ABS((**paraInfo).tabCount)];
*theStyleRun = styleRunPtr[styleRunIndex];
return theStyleRun->srStyleLen;
}
/* Get the style record. This will be fancier, reading off the disk, later */
void GetStyle(LongSTPtr theStyle, LongSTTable theStyleTable, long styleIndex)
{
*theStyle = (**theStyleTable).styleList[styleIndex];
}
/* Add a style run to the paragraph info. Fancier later */
OSErr AddStyleRun(LongStyleRunPtr theStyleRun, ParagraphInfoHandle paraInfo, long styleRunIndex)
{
if(theStyleRun->srIsGraphic)
theStyleRun->srIsTab = false;
Munger((Handle)paraInfo,
sizeof(ParagraphInfo) + (sizeof(short) * (ABS((**paraInfo).tabCount) - 1)) + (styleRunIndex * sizeof(LongStyleRun)),
nil, 0L, theStyleRun, sizeof(LongStyleRun));
return MemError();
}
OSErr DeleteStyle(LongSTTable theStyleTable, long styleIndex)
{
LongSTElement tempStyle;
OSErr errCode;
long numStyles;
GetStyle(&tempStyle, theStyleTable, styleIndex);
if (tempStyle.stCount > 0)
{
--tempStyle.stCount;
errCode = ChangeStyle(&tempStyle, theStyleTable, styleIndex);
if (errCode == noErr && tempStyle.stCount == 0L)
DeleteGraphicFromStyle(theStyleTable,styleIndex);
}
if(tempStyle.stCount == 0L) {
styleIndex = numStyles = NumStyles(theStyleTable);
do {
GetStyle(&tempStyle, theStyleTable, --styleIndex);
} while((tempStyle.stCount == 0L) && (styleIndex > 0L));
++styleIndex;
if(styleIndex != numStyles) {
SetHandleSize((Handle)theStyleTable, styleIndex * sizeof(LongSTElement) + sizeof(LongSTTable));
}
}
return errCode;
}
long FindStyleIndex(PETEStyleInfoPtr theStyle, LongSTTable theStyleTable, Boolean graphic);
long FindStyleIndex(PETEStyleInfoPtr theStyle, LongSTTable theStyleTable, Boolean graphic)
{
long styleIndex, numStyles;
LongSTElement tempStyle;
for(styleIndex = 0L, numStyles = NumStyles(theStyleTable); styleIndex < numStyles; ++styleIndex) {
GetStyle(&tempStyle, theStyleTable, styleIndex);
/* Check to see if the text styles are equal */
if((!graphic == !tempStyle.stIsGraphic) &&
((!graphic && EqualStyle((PETETextStylePtr)&tempStyle.stInfo.textStyle, &theStyle->textStyle)) ||
(graphic && EqualGraphic((PETEGraphicStylePtr)&tempStyle.stInfo.graphicStyle, &theStyle->graphicStyle)))) {
break;
}
}
return styleIndex;
}
/* Increment the style count or append the style to the style table */
OSErr AddStyle(PETEStyleInfoPtr newStyle, LongSTTable theStyleTable, unsigned long *curStyleIndex, Boolean graphic, Boolean printing)
{
long styleIndex;
LongSTElement tempStyle;
FMetricRec theMetrics;
PETEPortInfo savedPortInfo;
OSErr errCode;
styleIndex = FindStyleIndex(newStyle, theStyleTable, graphic);
if(styleIndex < NumStyles(theStyleTable)) {
GetStyle(&tempStyle, theStyleTable, styleIndex);
/* Increment the count field; there's on more occurance of this style */
++tempStyle.stCount;
/* Update the entry */
errCode = ChangeStyle(&tempStyle, theStyleTable, styleIndex);
} else {
/* The style was not found, so append a new one */
tempStyle.stInfo = *(StyleInfoPtr)newStyle;
tempStyle.stIsGraphic = !(!graphic);
SavePortInfo(nil, &savedPortInfo);
SetTextStyleWithDefaults(nil, (**theStyleTable).docInfo, &tempStyle.stInfo.textStyle, false, printing);
FontMetrics(&theMetrics);
ResetPortInfo(&savedPortInfo);
tempStyle.ascent = FixRound(theMetrics.ascent);
tempStyle.descent = FixRound(theMetrics.descent);
tempStyle.leading = FixRound(theMetrics.leading);
tempStyle.stCount = 1;
errCode = AppendStyle(&tempStyle, theStyleTable, &styleIndex);
if((errCode == noErr) && tempStyle.stIsGraphic) {
errCode = CallGraphic((**theStyleTable).docInfo, tempStyle.stInfo.graphicStyle.graphicInfo, kPETEOffsetUnknown, peGraphicInsert, nil);
if(errCode == invalidHandler) {
errCode = noErr;
}
}
}
/* If a style index needs to be returned, fill in the value */
if(curStyleIndex != nil) {
*curStyleIndex = styleIndex;
}
return errCode;
}
OSErr CompareStyles(PETEGlobalsHandle globals, DocumentInfoHandle docInfo, PETEStyleEntryPtr style1, PETEStyleEntryPtr style2, long validBits, Boolean printing, long *diffBits)
{
PETEStyleEntry s1, s2;
LongSTElement tempStyle;
*diffBits = 0L;
if(style1 == style2) {
return noErr;
}
if((style1 == nil) || (style2 == nil)) {
GetStyle(&tempStyle, (**docInfo).theStyleTable, 0L);
if(style1 == nil) {
s1.psGraphic = tempStyle.stIsGraphic;
s1.psStyle = tempStyle.stInfo;
s2 = *style2;
} else {
s2.psGraphic = tempStyle.stIsGraphic;
s2.psStyle = tempStyle.stInfo;
s1 = *style1;
}
} else {
s1 = *style1;
s2 = *style2;
}
if(validBits & peGraphicValid) {
if(!(!s1.psGraphic) != !(!s2.psGraphic)) {
*diffBits |= peGraphicValid;
} else if(s1.psGraphic) {
if(s1.psStyle.graphicStyle.graphicInfo != s2.psStyle.graphicStyle.graphicInfo) {
*diffBits |= peGraphicValid;
}
validBits &= ~peColorValid;
}
validBits &= ~peGraphicValid;
}
if(validBits & peColorValid) {
if(s1.psGraphic) {
s1.psGraphic = false;
SetPETEDefaultColor(s1.psStyle.textStyle.tsColor);
}
if(s2.psGraphic) {
s2.psGraphic = false;
SetPETEDefaultColor(s2.psStyle.textStyle.tsColor);
}
}
/* Do size before font because size might depend on original font */
if(validBits & peSizeValid) {
s1.psStyle.textStyle.tsSize = StyleToFontSize(globals, docInfo, &s1.psStyle.textStyle, printing);
s2.psStyle.textStyle.tsSize = StyleToFontSize(globals, docInfo, &s2.psStyle.textStyle, printing);
} else {
s1.psStyle.textStyle.tsSize = kPETEDefaultFont;
s2.psStyle.textStyle.tsSize = kPETEDefaultFont;
}
if(validBits & peFontValid) {
s1.psStyle.textStyle.tsFont = StyleToFont(globals, docInfo, &s1.psStyle.textStyle, printing);
s2.psStyle.textStyle.tsFont = StyleToFont(globals, docInfo, &s2.psStyle.textStyle, printing);
} else {
s1.psStyle.textStyle.tsFont = kPETEDefaultFont;
s2.psStyle.textStyle.tsFont = kPETEDefaultFont;
}
if(validBits & peColorValid) {
if(IsPETEDefaultColor(s1.psStyle.textStyle.tsColor)) {
s1.psStyle.textStyle.tsColor = DocOrGlobalColor(globals, docInfo);
}
if(IsPETEDefaultColor(s2.psStyle.textStyle.tsColor)) {
s2.psStyle.textStyle.tsColor = DocOrGlobalColor(globals, docInfo);
}
}
*diffBits |= ChangeStyleInfo(&s1.psStyle, &s2.psStyle, validBits, false);
return noErr;
}
/* Compare two text styles for equality */
Boolean EqualStyle(PETETextStylePtr theStyle1, PETETextStylePtr theStyle2)
{
return((theStyle1->tsFont == theStyle2->tsFont) &&
(theStyle1->tsFace == theStyle2->tsFace) &&
(theStyle1->tsSize == theStyle2->tsSize) &&
(theStyle1->tsColor.red == theStyle2->tsColor.red) &&
(theStyle1->tsColor.green == theStyle2->tsColor.green) &&
(theStyle1->tsColor.blue == theStyle2->tsColor.blue) &&
(theStyle1->tsLang == theStyle2->tsLang) &&
(theStyle1->tsLock == theStyle2->tsLock) &&
(theStyle1->tsLabel == theStyle2->tsLabel));
}
Boolean EqualGraphic(PETEGraphicStylePtr theStyle1, PETEGraphicStylePtr theStyle2)
{
return((theStyle1->tsFont == theStyle2->tsFont) &&
(theStyle1->tsFace == theStyle2->tsFace) &&
(theStyle1->tsSize == theStyle2->tsSize) &&
(theStyle1->graphicInfo == theStyle2->graphicInfo) &&
(theStyle1->tsLang == theStyle2->tsLang) &&
(theStyle1->tsLock == theStyle2->tsLock) &&
(theStyle1->tsLabel == theStyle2->tsLabel));
}
/* Count the number of styles in the style table */
long NumStyles(LongSTTable theStyleTable)
{
return (InlineGetHandleSize((Handle)theStyleTable) - sizeof(LongSTTable)) / sizeof(LongSTElement);
}
/* Add a new style to the style table */
OSErr AppendStyle(LongSTPtr theStyle, LongSTTable theStyleTable, long *styleIndex)
{
long styleCount = NumStyles(theStyleTable);
LongSTElement tempStyle;
if(theStyle->stIsGraphic && !GraphicInList((**(**theStyleTable).docInfo).globals, theStyle->stInfo.graphicStyle.graphicInfo))
{
return invalidHandler;
}
for(*styleIndex = 0L; *styleIndex < styleCount; ++*styleIndex) {
GetStyle(&tempStyle, theStyleTable, *styleIndex);
if(tempStyle.stCount == 0L) {
return ChangeStyle(theStyle, theStyleTable, *styleIndex);
}
}
return PtrAndHand(theStyle, (Handle)theStyleTable, sizeof(LongSTElement));
}
/* Update the information in a style entry; usually for incrementing the count */
OSErr ChangeStyle(LongSTPtr theStyle, LongSTTable theStyleTable, long styleIndex)
{
if(theStyle->stIsGraphic && !GraphicInList((**(**theStyleTable).docInfo).globals, theStyle->stInfo.graphicStyle.graphicInfo))
{
return invalidHandler;
}
(**theStyleTable).styleList[styleIndex] = *theStyle;
return noErr;
}
OSErr ChangeStyleRun(LongStyleRunPtr theStyleRun, ParagraphInfoHandle paraInfo, long styleRunIndex)
{
LongStyleRunPtr styleRunPtr;
styleRunPtr = (LongStyleRunPtr)&(**paraInfo).tabStops[ABS((**paraInfo).tabCount)];
styleRunPtr[styleRunIndex] = *theStyleRun;
return noErr;
}
void CompressStyleRuns(ParagraphInfoHandle paraInfo, LongSTTable theStyleTable, long styleRunIndex, long runsAdded)
{
LongStyleRun tempStyleRun1, tempStyleRun2;
if(styleRunIndex >= CountStyleRuns(paraInfo))
return;
do {
if(styleRunIndex != 0L) {
GetStyleRun(&tempStyleRun1, paraInfo, styleRunIndex - 1L);
GetStyleRun(&tempStyleRun2, paraInfo, styleRunIndex);
if((tempStyleRun1.srStyleIndex == tempStyleRun2.srStyleIndex) &&
!(tempStyleRun1.srIsTab || tempStyleRun2.srIsTab) &&
(tempStyleRun2.srStyleLen >= 0L)) {
tempStyleRun1.srStyleLen += tempStyleRun2.srStyleLen;
ChangeStyleRun(&tempStyleRun1, paraInfo, styleRunIndex - 1L);
DeleteStyleRun(paraInfo, theStyleTable, styleRunIndex);
} else if(tempStyleRun1.srStyleLen == 0L) {
DeleteStyleRun(paraInfo, theStyleTable, styleRunIndex - 1L);
} else {
++styleRunIndex;
}
--runsAdded;
} else {
++styleRunIndex;
}
} while(runsAdded > 0L);
}
/* Delete all of the styles of a given paragraph from the style table */
OSErr DeleteParaStyleRuns(ParagraphInfoHandle paraInfo, LongSTTable theStyleTable, long styleRunIndex, long runsToDelete)
{
OSErr errCode;
if(runsToDelete < 0L) {
runsToDelete = CountStyleRuns(paraInfo) - styleRunIndex;
}
/* Loop through all of the style runs in the paragraph */
for(errCode = noErr; (errCode == noErr) && (--runsToDelete >= 0L); ) {
errCode = DeleteStyleRun(paraInfo, theStyleTable, styleRunIndex + runsToDelete);
}
return (errCode == invalidIndexErr) ? noErr : errCode;
}
OSErr DeleteStyleRun(ParagraphInfoHandle paraInfo, LongSTTable theStyleTable, long styleRunIndex)
{
LongStyleRun tempStyleRun;
OSErr errCode;
if(styleRunIndex < CountStyleRuns(paraInfo)) {
GetStyleRun(&tempStyleRun, paraInfo, styleRunIndex);
errCode = RemoveStyleRuns(paraInfo, styleRunIndex, 1L);
if(errCode == noErr) {
errCode = DeleteStyle(theStyleTable, tempStyleRun.srStyleIndex);
}
} else {
errCode = invalidIndexErr;
}
return errCode;
}
OSErr RemoveStyleRuns(ParagraphInfoHandle paraInfo, long styleRunIndex, long styleRunCount)
{
long currentCount;
if(styleRunCount == 0L) {
return noErr;
}
currentCount = CountStyleRuns(paraInfo);
if(styleRunIndex == currentCount) {
return noErr;
}
if(styleRunIndex + styleRunCount > currentCount) {
return inputOutOfBounds;
}
if((styleRunIndex < 0L) || (styleRunCount < 0L)) {
return inputOutOfBounds;
}
Munger((Handle)paraInfo,
sizeof(ParagraphInfo) + (sizeof(short) * (ABS((**paraInfo).tabCount) - 1)) + (styleRunIndex * sizeof(LongStyleRun)),
nil, sizeof(LongStyleRun) * styleRunCount, (Ptr)1L, 0L);
return MemError();
}
OSErr GetGraphicInfoFromOffset(DocumentInfoHandle docInfo, long offset, GraphicInfoHandle *graphicInfo, long *length)
{
OSErr errCode;
PETEStyleEntry tempStyle;
errCode = GetStyleFromOffset(docInfo, offset, length, &tempStyle);
if(errCode == noErr) {
*graphicInfo = tempStyle.psStyle.graphicStyle.graphicInfo;
}
return errCode;
}
OSErr GetStyleFromOffset(DocumentInfoHandle docInfo, long offset, long *length, PETEStyleEntryPtr theStyle)
{
SelData selection;
LongStyleRun tempStyleRun;
LongSTElement tempStyle;
OSErr errCode;
if(offset == kPETEDefaultStyle) {
if(theStyle != nil) {
GetStyle(&tempStyle, (**docInfo).theStyleTable, 0L);
theStyle->psStartChar = 0L;
theStyle->psGraphic = tempStyle.stIsGraphic;
theStyle->psStyle = tempStyle.stInfo;
}
return noErr;
} else if(offset == kPETECurrentStyle) {
if(theStyle != nil) {
theStyle->psStartChar = 0L;
theStyle->psGraphic = 0L;
theStyle->psStyle.textStyle = (**docInfo).curTextStyle;
}
return noErr;
}
if(offset == kPETECurrentSelection) {
offset = (**docInfo).selStart.offset;
}
if(offset < 0L) {
return errOffsetInvalid;
}
if(offset >= (**docInfo).textLen) {
offset = (**docInfo).textLen - 1L;
}
selection.offset = offset;
selection.paraIndex = ParagraphIndex(docInfo, offset);
selection.lastLine = false;
selection.leadingEdge = true;
errCode = GetSelectionStyle(docInfo, &selection, &tempStyleRun, &offset, nil);
if(errCode != noErr) {
return noErr;
}
GetStyle(&tempStyle, (**docInfo).theStyleTable, tempStyleRun.srStyleIndex);
if(length != nil) {
*length = tempStyleRun.srStyleLen;
}
if(theStyle != nil) {
theStyle->psStartChar = selection.offset - offset;
theStyle->psGraphic = tempStyle.stIsGraphic;
theStyle->psStyle = tempStyle.stInfo;
}
return noErr;
}
OSErr GetSelectionStyle(DocumentInfoHandle docInfo, SelDataPtr selection, LongStyleRunPtr styleRun, long *styleRunOffset, MyTextStylePtr textStyle)
{
ParagraphInfoHandle paraInfo;
long offset;
LongStyleRun tempStyleRun;
LongSTElement tempStyle;
OSErr errCode;
if(!selection->lastLine && !selection->leadingEdge) {
errCode = CheckParagraphMeasure(docInfo, selection->paraIndex, true);
if(errCode != noErr) {
return errCode;
}
}
offset = selection->offset;
/* Get the line starts information for the paragraph */
paraInfo = (**docInfo).paraArray[selection->paraIndex].paraInfo;
if(selection->lastLine || (!selection->leadingEdge && (offset != (*(**paraInfo).lineStarts)[selection->lineIndex].lsStartChar))) {
--offset;
}
offset -= ParagraphOffset(docInfo, selection->paraIndex);
if(offset < 0L)
offset = 0L;
GetStyleRun(&tempStyleRun, paraInfo, StyleRunIndex(paraInfo, &offset));
if(styleRun != nil) {
*styleRun = tempStyleRun;
}
if(styleRunOffset != nil) {
*styleRunOffset = offset;
}
if(textStyle != nil) {
GetStyle(&tempStyle, (**docInfo).theStyleTable, tempStyleRun.srStyleIndex);
*textStyle = tempStyle.stInfo.textStyle;
if(tempStyleRun.srIsGraphic) {
SetPETEDefaultColor(textStyle->tsColor);
}
}
return noErr;
}
/* Insert style information into a paragraph and style table */
OSErr StyleListToStyles(ParagraphInfoHandle paraInfo, LongSTTable theStyleTable, Ptr theText, long textSize, long hOffset, long textOffset, Handle listHandle, long listOffset, MyTextStylePtr textStyle, Boolean printing)
{
PETEStyleList styleList;
LongStyleRun tempStyleRun;
LongSTElement tempStyle;
long listSize, runOffset, nextStart, nextTab, tabCount, thisStart, textLen, runsAdded, styleRunIndex, tempOffset;
unsigned long tempStyleIndex;
OSErr errCode;
Boolean splitStyleRun;
/* Initialize stuff */
runsAdded = 0L;
nextTab = -1L;
tabCount = 1L;
errCode = noErr;
splitStyleRun = false;
if(textSize < 0L) {
textLen = InlineGetHandleSize((Handle)theText);
hOffset = 0L;
} else {
textLen = textSize;
}
/* Is there a style list provided */
if((listHandle != nil) && (listHandle != (Handle)-1L)) {
/* Yes, so get the size of styles */
listSize = InlineGetHandleSize(listHandle) - listOffset;
} else {
/* No, so this is just one style run */
listSize = sizeof(PETEStyleEntry);
}
tempOffset = textOffset;
styleRunIndex = StyleRunIndex(paraInfo, &tempOffset);
if(tempOffset != 0L) {
GetStyleRun(&tempStyleRun, paraInfo, styleRunIndex);
GetStyle(&tempStyle, theStyleTable, tempStyleRun.srStyleIndex);
errCode = AddStyle(&tempStyle.stInfo, theStyleTable, &tempStyleIndex, tempStyleRun.srIsGraphic, printing);
tempStyleRun.srStyleIndex = tempStyleIndex;
if(errCode == noErr) {
tempStyleRun.srStyleLen -= tempOffset;
errCode = AddStyleRun(&tempStyleRun, paraInfo, styleRunIndex + 1L);
if(errCode == noErr) {
tempStyleRun.srStyleLen = tempOffset;
errCode = ChangeStyleRun(&tempStyleRun, paraInfo, styleRunIndex);
if(errCode == noErr) {
splitStyleRun = true;
++styleRunIndex;
} else {
DeleteStyleRun(paraInfo, theStyleTable, styleRunIndex + 1L);
}
} else {
DeleteStyle(theStyleTable, tempStyleRun.srStyleIndex);
}
}
}
/* Loop through all of the style runs in the scrap */
for(runOffset = 0L; errCode == noErr && runOffset < listSize; runOffset += sizeof(PETEStyleEntry)) {
if((listHandle != nil) && (listHandle != (Handle)-1L)) {
/* The beginning of the style list is listOffset into listHandle */
styleList = (PETEStyleList)(*listHandle + listOffset + runOffset);
/* Get the style from the list */
tempStyle.stInfo = styleList->psStyle;
tempStyleRun.srIsGraphic = !(!(styleList->psGraphic & 1L));
/* Get the starting position of this style run */
thisStart = styleList->psStartChar;
} else {
/* There is no style list, so set up for plain text in the current style */
if(listHandle != nil) {
GetStyle(&tempStyle, theStyleTable, 0L);
} else {
tempStyle.stInfo.textStyle = *textStyle;
tempStyleRun.srIsGraphic = false;
}
thisStart = 0L;
}
if(runOffset + sizeof(PETEStyleEntry) != listSize) {
/* If this isn't the last run, get the start of the next run */
nextStart = (styleList + 1L)->psStartChar;
if(nextStart >= textLen) {
runOffset = listSize;
goto SetToTextLen;
}
} else {
SetToTextLen :
/* If this is the last run, get the length of the whole text */
nextStart = textLen;
}
do {
/* Find the next tab in the text if it's not set up */
if(thisStart > nextTab) {
do {
nextTab = FindNextTab((((textSize < 0L) || (hOffset >= 0L)) ? *(Handle)theText + hOffset : theText), textLen, nextTab, &tabCount);
/* Skip tabs in graphics */
} while(tempStyleRun.srIsGraphic && (nextStart < nextTab) && (nextTab < textLen));
}
tempStyleRun.srIsTab = false;
/* Is there a tab in this style run? */
if(nextTab <= nextStart) {
/* Yes. Is the tab at the beginning of the style run? */
if(nextTab > thisStart) {
/* No, so say that this style run length is up to the tab */
tempStyleRun.srStyleLen = nextTab - thisStart;
/* Next time around, the style run begins at the tab */
thisStart = nextTab;
} else {
/* Move thisStart past the tab */
++thisStart;
/* Only one tab per style run */
tempStyleRun.srStyleLen = 1L;
/* Is there more than one tab in this style run? */
if(tabCount > 1L) {
/* Get the next tab next time */
--tabCount;
nextTab = thisStart;
}
tempStyleRun.srIsTab = true;
}
} else {
/* No tabs, so just use the regular length */
tempStyleRun.srStyleLen = nextStart - thisStart;
}
/* Add to the style table */
errCode = AddStyle(&tempStyle.stInfo, theStyleTable, &tempStyleIndex, tempStyleRun.srIsGraphic, printing);
tempStyleRun.srStyleIndex = tempStyleIndex;
if(errCode == noErr) {
/* Add the style run to the paragraph info */
errCode = AddStyleRun(&tempStyleRun, paraInfo, styleRunIndex + runsAdded);
/* If an error occurred adding the style run, remove the style entry */
if(errCode != noErr) {
DeleteStyle(theStyleTable, tempStyleRun.srStyleIndex);
} else {
++runsAdded;
}
}
/* Loop around while dealing with tabs */
} while((errCode == noErr) && (nextTab <= nextStart) && (thisStart < nextStart));
}
/* If an error occurred, clean out all of the style entries */
if(errCode != noErr) {
DeleteParaStyleRuns(paraInfo, theStyleTable, styleRunIndex, runsAdded);
}
if((runsAdded > 0L) || splitStyleRun) {
CompressStyleRuns(paraInfo, theStyleTable, styleRunIndex, runsAdded + (splitStyleRun ? 1L : 0L));
}
return errCode;
}
OSErr ChangeStyleRange(DocumentInfoHandle docInfo, long startOffset, long endOffset, StyleInfoPtr newStyle, long validBits)
{
long styleRunIndex, startStyleRunIndex, endStyleRunIndex, paraIndex, endParaIndex, curOffset, endRunOffset;
unsigned long tempStyleIndex;
ParagraphInfoHandle paraInfo;
LongStyleRun tempStyleRun, oldStyleRun;
LongSTElement tempStyle, endStyle;
Boolean endIsTab, doUndo, wasChanged;
OSErr errCode;
if(((startOffset < -1L) || (endOffset < -1L)) && (startOffset != endOffset)) {
return errAEImpossibleRange;
}
if((validBits & peGraphicValid) && ((validBits & peColorValid) || (startOffset == kPETEDefaultStyle) || (startOffset == kPETECurrentStyle))) {
return paramErr;
}
/* Turn off caret just in case there's a redraw */
EraseCaret(docInfo);
/* If kPETEDefaultStyle, just change style 0 in the table */
if(startOffset == kPETEDefaultStyle) {
GetStyle(&tempStyle, (**docInfo).theStyleTable, 0L);
if(ChangeStyleInfo(newStyle, &tempStyle.stInfo, validBits, false) && (ChangeStyle(&tempStyle, (**docInfo).theStyleTable, 0L), ((validBits & ~peLockValid) != 0L))) {
return ResetAndInvalidateDocument(docInfo);
} else {
return noErr;
}
}
doUndo = false;
/* If the values are both negative, the current style must change */
if((startOffset < 0L) && (endOffset < 0L)) {
tempStyle.stInfo.textStyle = (**docInfo).curTextStyle;
ChangeStyleInfo(newStyle, &tempStyle.stInfo, validBits, false);
(**docInfo).curTextStyle = tempStyle.stInfo.textStyle;
if(validBits & peFontValid) {
SetStyleAndKeyboard(docInfo, &tempStyle.stInfo.textStyle);
}
if(startOffset == kPETECurrentSelection) {
doUndo = true;
}
}
/* If only the current style is changing, return */
if(startOffset == kPETECurrentStyle) {
return noErr;
}
/* Fix up the offsets */
if(endOffset < 0L) {
endOffset = (**docInfo).selEnd.offset;
} else if(endOffset > (**docInfo).textLen) {
endOffset = (**docInfo).textLen;
}
if(startOffset < 0L) {
startOffset = (**docInfo).selStart.offset;
}
if(startOffset > endOffset) {
return errAEImpossibleRange;
} else if(startOffset == endOffset) {
return noErr;
}
if(doUndo) {
errCode = SetParaStyleUndo(docInfo, startOffset, endOffset, peUndoStyle);
if(errCode != noErr) {
return errCode;
}
}
/* Get the starting and ending paragraphs */
paraIndex = ParagraphIndex(docInfo, startOffset);
endParaIndex = ParagraphIndex(docInfo, endOffset - 1L);
/* Get the offsets into the starting and ending paragraph */
curOffset = startOffset - ParagraphOffset(docInfo, paraIndex);
endRunOffset = endOffset - ParagraphOffset(docInfo, endParaIndex) - 1L;
paraInfo = (**docInfo).paraArray[endParaIndex].paraInfo;
/* Get the ending style run index and the offset into that style run */
endStyleRunIndex = StyleRunIndex(paraInfo, &endRunOffset);
/* Get the ending style itself */
GetStyleRun(&tempStyleRun, paraInfo, endStyleRunIndex);
endIsTab = tempStyleRun.srIsTab;
GetStyle(&endStyle, (**docInfo).theStyleTable, tempStyleRun.srStyleIndex);
++endRunOffset;
paraInfo = (**docInfo).paraArray[paraIndex].paraInfo;
/* Get the starting style run index and offset into that style run */
styleRunIndex = StyleRunIndex(paraInfo, &curOffset);
/* Increment before entering the loop */
startStyleRunIndex = styleRunIndex + 1L;
/* If only one style run is being changed, subtract off the beginning of the style run */
if((paraIndex == endParaIndex) && (styleRunIndex == endStyleRunIndex)) {
endRunOffset -= curOffset;
}
wasChanged = false;
do {
(**docInfo).flags.scrollsDirty = true;
/* Get the style of the current style run */
GetStyleRun(&tempStyleRun, paraInfo, styleRunIndex);
GetStyle(&tempStyle, (**docInfo).theStyleTable, tempStyleRun.srStyleIndex);
/* Change the style according to the parameters */
if(ChangeStyleInfo(newStyle, &tempStyle.stInfo, validBits, tempStyleRun.srIsGraphic)) {
wasChanged = true;
}
if(wasChanged) {
/* Save the style run info */
oldStyleRun = tempStyleRun;
if(validBits & peGraphicColorChangeValid) {
/* Set the graphic flag if needed */
if(validBits & peGraphicValid) {
tempStyleRun.srIsGraphic = true;
tempStyleRun.srIsTab = false;
endIsTab = false;
} else if(validBits & peColorValid) {
tempStyleRun.srIsGraphic = false;
//! /* Probably have to look for tabs here some day */
}
}
/* Add the new style to the style table */
errCode = AddStyle(&tempStyle.stInfo, (**docInfo).theStyleTable, &tempStyleIndex, tempStyleRun.srIsGraphic, ((**docInfo).printData != nil));
tempStyleRun.srStyleIndex = tempStyleIndex;
if(errCode != noErr) {
break;
}
/* If part way into a style run, split the style run */
if(curOffset != 0L) {
/* Set the new length correctly */
tempStyleRun.srStyleLen -= curOffset;
/* Add the second part of the style run as new and increment the index */
errCode = AddStyleRun(&tempStyleRun, paraInfo, ++styleRunIndex);
if(errCode != noErr) {
/* Delete what was added to the table on errors */
DeleteStyle((**docInfo).theStyleTable, tempStyleRun.srStyleIndex);
break;
}
/* Change the first part of the style run to the length of whatever's unchanged */
oldStyleRun.srStyleLen = curOffset;
errCode = ChangeStyleRun(&oldStyleRun, paraInfo, styleRunIndex - 1L);
if(errCode != noErr) {
/* Delete the newly added style run on errors */
DeleteStyleRun(paraInfo, (**docInfo).theStyleTable, styleRunIndex);
break;
}
/* If the start and end paras were the same, increment the end style run too */
if(paraIndex == endParaIndex) {
++endStyleRunIndex;
}
/* The next time through will be from the beginning of a style run */
curOffset = 0L;
} else {
/* Delete the style for this style run; it will be changed to the new style */
errCode = DeleteStyle((**docInfo).theStyleTable, oldStyleRun.srStyleIndex);
if(errCode != noErr) {
DeleteStyle((**docInfo).theStyleTable, tempStyleRun.srStyleIndex);
break;
}
/* Change the style run to the newly created style */
ChangeStyleRun(&tempStyleRun, paraInfo, styleRunIndex++);
}
if((paraIndex == endParaIndex) && (styleRunIndex == endStyleRunIndex + 1L)) {
if((endRunOffset < tempStyleRun.srStyleLen) && !endIsTab) {
errCode = AddStyle(&endStyle.stInfo, (**docInfo).theStyleTable, &tempStyleIndex, endStyle.stIsGraphic, ((**docInfo).printData != nil));
if(errCode != noErr) {
break;
}
tempStyleRun.srStyleLen -= endRunOffset;
tempStyleRun.srIsGraphic = endStyle.stIsGraphic;
tempStyleRun.srIsTab = false;
Exchange(tempStyleRun.srStyleIndex, tempStyleIndex);
errCode = AddStyleRun(&tempStyleRun, paraInfo, styleRunIndex);
if(errCode != noErr) {
DeleteStyle((**docInfo).theStyleTable, tempStyleRun.srStyleIndex);
break;
}
tempStyleRun.srStyleLen = endRunOffset;
tempStyleRun.srStyleIndex = tempStyleIndex;
errCode = ChangeStyleRun(&tempStyleRun, paraInfo, styleRunIndex - 1L);
if(errCode != noErr) {
DeleteStyleRun(paraInfo, (**docInfo).theStyleTable, styleRunIndex);
break;
}
}
DoParaRecalc(docInfo, paraIndex, startOffset, endOffset, startStyleRunIndex, styleRunIndex, validBits);
} else {
if(styleRunIndex == CountStyleRuns(paraInfo)) {
DoParaRecalc(docInfo, paraIndex, startOffset, endOffset, startStyleRunIndex, styleRunIndex, validBits);
styleRunIndex = 0L;
++paraIndex;
if(paraIndex < (**docInfo).paraCount) {
startStyleRunIndex = 1L;
paraInfo = (**docInfo).paraArray[paraIndex].paraInfo;
}
}
}
} else {
errCode = noErr;
curOffset = 0L;
++styleRunIndex;
++startStyleRunIndex;
if((paraIndex == endParaIndex) && (styleRunIndex == endStyleRunIndex + 1L)) {
continue;
} else if(styleRunIndex == CountStyleRuns(paraInfo)) {
styleRunIndex = 0L;
++paraIndex;
if(paraIndex < (**docInfo).paraCount) {
startStyleRunIndex = 1L;
paraInfo = (**docInfo).paraArray[paraIndex].paraInfo;
}
}
}
} while((paraIndex < (**docInfo).paraCount) && ((paraIndex != endParaIndex) || (styleRunIndex <= endStyleRunIndex)));
if((errCode == noErr) && wasChanged) {
if((validBits & ~peLockValid) != 0) {
ResetScrollbars(docInfo);
DeleteIdleGraphics(docInfo, startOffset, endOffset);
NewIdleGraphics(docInfo, startOffset, endOffset);
}
FlushDocInfoLineCache(docInfo);
SetDirty(docInfo, startOffset, endOffset, true);
}
return errCode;
}
long ChangeStyleInfo(StyleInfoPtr sourceStyle, StyleInfoPtr destStyle, long validBits, Boolean isGraphic)
{
long changedBits = 0L, tempBits;
if((validBits & peColorValid) && (validBits & peGraphicValid)) {
return 0L;
}
if((validBits & peGraphicValid) && (validBits & peGraphicColorChangeValid) && !isGraphic) {
changedBits |= peColorValid;
changedBits |= peGraphicValid;
}
if((validBits & peColorValid) && (validBits & peGraphicColorChangeValid) && isGraphic) {
changedBits |= peColorValid;
changedBits |= peGraphicValid;
}
if((validBits & peFontValid) && (destStyle->textStyle.tsFont != sourceStyle->textStyle.tsFont)) {
destStyle->textStyle.tsFont = sourceStyle->textStyle.tsFont;
changedBits |= peFontValid;
}
if((tempBits = ((destStyle->textStyle.tsFace ^ sourceStyle->textStyle.tsFace) & validBits)) != 0L) {
destStyle->textStyle.tsFace &= ~validBits;
destStyle->textStyle.tsFace |= (validBits & sourceStyle->textStyle.tsFace);
changedBits |= tempBits;
}
if((validBits & peSizeValid) && (destStyle->textStyle.tsSize != sourceStyle->textStyle.tsSize)) {
destStyle->textStyle.tsSize = sourceStyle->textStyle.tsSize;
changedBits |= peSizeValid;
}
if((validBits & peColorValid) && ((validBits & peGraphicColorChangeValid) || !isGraphic) && ((destStyle->textStyle.tsColor.red != sourceStyle->textStyle.tsColor.red) || (destStyle->textStyle.tsColor.green != sourceStyle->textStyle.tsColor.green) || (destStyle->textStyle.tsColor.blue != sourceStyle->textStyle.tsColor.blue))) {
destStyle->textStyle.tsColor = sourceStyle->textStyle.tsColor;
changedBits |= peColorValid;
}
if((validBits & peGraphicValid) && ((validBits & peGraphicColorChangeValid) || isGraphic) && (destStyle->graphicStyle.graphicInfo != sourceStyle->graphicStyle.graphicInfo)) {
destStyle->graphicStyle.graphicInfo = sourceStyle->graphicStyle.graphicInfo;
changedBits |= peGraphicValid;
}
if((validBits & peLangValid) && (destStyle->textStyle.tsLang != sourceStyle->textStyle.tsLang)) {
destStyle->textStyle.tsLang = sourceStyle->textStyle.tsLang;
changedBits |= peLangValid;
}
if((tempBits = ((((long)(destStyle->textStyle.tsLock ^ sourceStyle->textStyle.tsLock)) << kPETELockShift) & validBits)) != 0L){
destStyle->textStyle.tsLock &= ~((validBits >> kPETELockShift) & 0x0000000F);
destStyle->textStyle.tsLock |= (sourceStyle->textStyle.tsLock & ((validBits >> kPETELockShift) & 0x0000000F));
changedBits |= tempBits;
}
if((tempBits = ((((long)(destStyle->textStyle.tsLabel ^ sourceStyle->textStyle.tsLabel)) << kPETELabelShift) & validBits)) != 0L) {
destStyle->textStyle.tsLabel &= ~((validBits >> kPETELabelShift) & 0x00000FFF);
destStyle->textStyle.tsLabel |= (sourceStyle->textStyle.tsLabel & ((validBits >> kPETELabelShift) & 0x00000FFF));
changedBits |= tempBits;
}
return changedBits;
}
OSErr FindLabelRun(DocumentInfoHandle docInfo, long offset, long *start, long *end, unsigned short label, unsigned short mask)
{
long paraIndex, styleRunIndex, startOffset, tempOffset, styleRunLen, styleRunCount;
ParagraphInfoHandle paraInfo;
LongSTElement tempStyle;
LongStyleRun tempStyleRun;
if(offset >= (**docInfo).textLen) {
return errOffsetInvalid;
}
*start = -2L;
startOffset = offset;
paraIndex = ParagraphIndex(docInfo, offset);
paraInfo = (**docInfo).paraArray[paraIndex].paraInfo;
tempOffset = offset - ParagraphOffset(docInfo, paraIndex);
styleRunIndex = StyleRunIndex(paraInfo, &tempOffset);
offset -= tempOffset;
styleRunCount = CountStyleRuns(paraInfo);
do {
styleRunLen = GetStyleRun(&tempStyleRun, paraInfo, styleRunIndex);
GetStyle(&tempStyle, (**docInfo).theStyleTable, tempStyleRun.srStyleIndex);
if((tempStyle.stInfo.textStyle.tsLabel & mask) == (label & mask)) {
if(offset <= startOffset) {
if(*start < -1L) {
++*start;
} else if(styleRunIndex != 0L || paraIndex != 0L) {
offset -= styleRunLen;
}
if(--styleRunIndex >= 0L || paraIndex != 0L) {
if(styleRunIndex < 0L) {
--paraIndex;
paraInfo = (**docInfo).paraArray[paraIndex].paraInfo;
styleRunCount = CountStyleRuns(paraInfo);
styleRunIndex = styleRunCount - 1L;
}
} else {
offset = 0L;
startOffset = -1L;
++styleRunIndex;
}
continue;
} else if(*start < 0L) {
*start = offset;
}
} else if(*start >= 0L) {
break;
} else if((offset <= startOffset) && (*start == -1L)) {
startOffset = offset - 1L;
offset -= styleRunLen;
}
offset += styleRunLen;
if(++styleRunIndex >= styleRunCount) {
if(++paraIndex < (**docInfo).paraCount) {
paraInfo = (**docInfo).paraArray[paraIndex].paraInfo;
styleRunCount = CountStyleRuns(paraInfo);
styleRunIndex = 0L;
} else {
break;
}
}
} while(true);
if(*start < 0L) {
return errEndOfDocument;
} else {
*end = offset;
return noErr;
}
}
OSErr ApplyStyleList(DocumentInfoHandle docInfo, long startOffset, long endOffset, PETEStyleListHandle styleScrap)
{
long styleCount, styleIndex, currentLength, currentOffset;
short validBits;
OSErr errCode;
StyleInfo style;
styleCount = InlineGetHandleSize((Handle)styleScrap) / sizeof(PETEStyleEntry);
if(styleCount < 0L) {
return MemError();
}
if((styleCount == 0L) || ((*styleScrap)[styleCount - 1L].psStartChar + startOffset >= endOffset)) {
return errOffsetInvalid;
}
errCode = noErr;
for(styleIndex = 0L; styleIndex < styleCount && errCode == noErr; ++styleIndex) {
style = (*styleScrap)[styleIndex].psStyle;
validBits = peAllValid;
if((*styleScrap)[styleIndex].psGraphic) {
validBits &= ~peColorValid;
}
currentOffset = startOffset + (*styleScrap)[styleIndex].psStartChar;
if(styleIndex == styleCount - 1L) {
currentLength = endOffset - currentOffset;
} else {
currentLength = (*styleScrap)[styleIndex + 1L].psStartChar - (*styleScrap)[styleIndex].psStartChar;
}
errCode = ChangeStyleRange(docInfo, currentOffset, currentOffset + currentLength, &style, validBits);
}
return errCode;
}
Boolean SameGraphic(DocumentInfoHandle docInfo, SelDataPtr selection)
{
if(((**docInfo).selectedGraphic == nil) || !selection->graphicHit) {
return false;
}
if(selection->offset == (**docInfo).selStart.offset) {
return selection->leadingEdge;
}
if(selection->offset == (**docInfo).selEnd.offset) {
return !selection->leadingEdge;
}
return((selection->offset > (**docInfo).selStart.offset) && (selection->offset < (**docInfo).selEnd.offset));
}
void RecalcStyleHeights(PETEGlobalsHandle globals, DocumentInfoHandle docInfo, Boolean printing)
{
long styleIndex;
PETEPortInfo savedPortInfo;
FMetricRec theMetrics;
LongSTElement tempStyle;
SavePortInfo(nil, &savedPortInfo);
for(styleIndex = NumStyles((**docInfo).theStyleTable); --styleIndex >= 0L; ) {
GetStyle(&tempStyle, (**docInfo).theStyleTable, styleIndex);
if(!tempStyle.stIsGraphic) {
SetTextStyleWithDefaults(globals, docInfo, &tempStyle.stInfo.textStyle, false, printing);
FontMetrics(&theMetrics);
tempStyle.ascent = FixRound(theMetrics.ascent);
tempStyle.descent = FixRound(theMetrics.descent);
tempStyle.leading = FixRound(theMetrics.leading);
ChangeStyle(&tempStyle, (**docInfo).theStyleTable, styleIndex);
}
}
ResetPortInfo(&savedPortInfo);
}
void AddScrapStyles(LongSTTable theStyleTable, PETEStyleListHandle styleScrap)
{
long entryCount;
PETEStyleInfo tempStyle;
entryCount = InlineGetHandleSize((Handle)styleScrap) / sizeof(PETEStyleEntry);
while(--entryCount >= 0L) {
tempStyle = (*styleScrap)[entryCount].psStyle;
AddStyle(&tempStyle, theStyleTable, nil, (*styleScrap)[entryCount].psGraphic, ((**(**theStyleTable).docInfo).printData != nil));
}
}
void DeleteScrapStyles(LongSTTable theStyleTable, PETEStyleListHandle styleScrap)
{
long entryCount, styleIndex;
PETEStyleInfo tempStyle;
entryCount = InlineGetHandleSize((Handle)styleScrap) / sizeof(PETEStyleEntry);
while(--entryCount >= 0L) {
tempStyle = (*styleScrap)[entryCount].psStyle;
styleIndex = FindStyleIndex(&tempStyle, theStyleTable, (*styleScrap)[entryCount].psGraphic);
DeleteStyle(theStyleTable, styleIndex);
}
}
void GetCurrentTextStyle(DocumentInfoHandle docInfo, MyTextStylePtr textStyle)
{
ScriptCode scriptCode;
long scriptCount;
*textStyle = (**docInfo).curTextStyle;
if(((**docInfo).flags.isActive) && ((**(**docInfo).globals).flags.hasMultiScript)) {
scriptCode = (short)GetScriptManagerVariable(smKeyScript);
if(scriptCode != StyleToScript(textStyle)) {
scriptCount = (**(**docInfo).lastFont).scriptCount;
while(--scriptCount >= 0L) {
if((**(**docInfo).lastFont).scriptFontList[scriptCount].theScript == scriptCode) {
textStyle->tsFont = (**(**docInfo).lastFont).scriptFontList[scriptCount].theFont;
break;
}
}
if(scriptCount < 0L) {
textStyle->tsFont = kPETEDefaultFont;
}
textStyle->tsLang = (short)GetScriptVariable(scriptCode, smScriptLang);
(**docInfo).curTextStyle = *textStyle;
}
}
}
OSErr GetStylesForMenu(DocumentInfoHandle docInfo, MyTextStylePtr curTextStyle, PETEStylesForMenuPtr selectionStyles)
{
#pragma unused (docInfo,curTextStyle,selectionStyles)
return paramErr;
}