1 line
37 KiB
C
Executable File
1 line
37 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 DrawListBullet(DocumentInfoHandle docInfo, long paraIndex, short leftPosition, short ascent);
|
|
|
|
/* Draw the document in its window from an outside call */
|
|
OSErr UpdateDocument(DocumentInfoHandle docInfo)
|
|
{
|
|
OSErr errCode;
|
|
RgnHandle scratchRgn, tempRgn;
|
|
Rect viewRect;
|
|
PETEPortInfo savedPortInfo;
|
|
|
|
if((**docInfo).printData != nil) {
|
|
errCode = DrawDocumentWithPicture(docInfo);
|
|
} else if((**docInfo).flags.progressLoopCalled || (**docInfo).flags.updating) {
|
|
(**docInfo).flags.drawInProgressLoop = true;
|
|
errCode = noErr;
|
|
goto AddToUpdateRgn;
|
|
} else {
|
|
(**docInfo).flags.updating = true;
|
|
errCode = DrawDocument(docInfo, nil, true);
|
|
(**docInfo).flags.updating = false;
|
|
if(errCode == cantDoThatInCurrentMode) {
|
|
AddToUpdateRgn :
|
|
tempRgn = NewRgn();
|
|
if(tempRgn != nil) {
|
|
scratchRgn = (**(**docInfo).globals).scratchRgn;
|
|
SavePortInfo(((**docInfo).printData == nil) ? GetWindowPort((**docInfo).docWindow) : (**(**docInfo).printData).pPort, &savedPortInfo);
|
|
GetClip(scratchRgn);
|
|
if((**docInfo).printData == nil) {
|
|
GetVisibleRgn(tempRgn);
|
|
SectRgn(tempRgn, scratchRgn, scratchRgn);
|
|
}
|
|
ResetPortInfo(&savedPortInfo);
|
|
viewRect = (**docInfo).viewRect;
|
|
RectRgn(tempRgn, &viewRect);
|
|
SectRgn(tempRgn, scratchRgn, scratchRgn);
|
|
DisposeRgn(tempRgn);
|
|
UnionRgn(scratchRgn, (**docInfo).updateRgn, (**docInfo).updateRgn);
|
|
} else {
|
|
errCode = memFullErr;
|
|
}
|
|
}
|
|
}
|
|
return errCode;
|
|
}
|
|
|
|
/* Draw the entire document in its window */
|
|
OSErr DrawDocument(DocumentInfoHandle docInfo, RgnHandle clipRgn, Boolean preserveLine)
|
|
{
|
|
long paraIndex;
|
|
short lineIndex, lineCount, curV;
|
|
LSTable lineStarts;
|
|
Rect drawRect, lineRect;
|
|
LayoutCache lineCache;
|
|
PETEPortInfo savedPortInfo;
|
|
RgnHandle oldClip, scratchRgn, newClip;
|
|
LineInfo lineInfo;
|
|
CGrafPtr savedGWorld, newGWorld;
|
|
GDHandle savedGDevice;
|
|
GWorldPtr offscreenGWorld;
|
|
GWorldFlags gFlags;
|
|
PixMapHandle pixMap, tempPixMap;
|
|
RGBColor backColor /* = {0xffff,0xffff,0xffff} */;
|
|
QDErr errCode;
|
|
Byte hState;
|
|
|
|
/* Stupid compiler */
|
|
backColor.red = backColor.green = backColor.blue = 0xffff;
|
|
|
|
scratchRgn = (**(**docInfo).globals).scratchRgn;
|
|
|
|
/* Create region for old clip region */
|
|
oldClip = NewRgn();
|
|
if(oldClip == nil) {
|
|
return memFullErr;
|
|
}
|
|
|
|
/* Create region for new clip region */
|
|
newClip = NewRgn();
|
|
if(newClip == nil) {
|
|
DisposeRgn(oldClip);
|
|
return memFullErr;
|
|
}
|
|
|
|
/* Save old port info */
|
|
newGWorld = ((**docInfo).printData == nil) ? GetWindowPort((**docInfo).docWindow) : (**(**docInfo).printData).pPort;
|
|
if((**docInfo).flags.embedded && ((**(**docInfo).globals).savedGWorld == newGWorld))
|
|
newGWorld = (**(**docInfo).globals).offscreenGWorld;
|
|
SavePortInfo(newGWorld, &savedPortInfo);
|
|
|
|
/* Get the view rect region */
|
|
drawRect = (**docInfo).viewRect;
|
|
RectRgn(newClip, &drawRect);
|
|
|
|
if((**docInfo).printData == nil) {
|
|
/* Clip down to the visRgn. Though this is automatic, the rgnBBox is used later */
|
|
GetVisibleRgn(oldClip);
|
|
SectRgn(oldClip, newClip, newClip);
|
|
}
|
|
|
|
/* Clip down to the old clipping region */
|
|
GetClip(oldClip);
|
|
SectRgn(oldClip, newClip, newClip);
|
|
|
|
if(clipRgn != nil) {
|
|
SectRgn(clipRgn, newClip, newClip);
|
|
}
|
|
|
|
SetClip(newClip);
|
|
DiffRgn((**docInfo).graphicRgn, newClip, (**docInfo).graphicRgn);
|
|
|
|
backColor = DocOrGlobalBGColor(nil, docInfo);
|
|
if(!IsPETEDefaultColor(backColor)) {
|
|
RGBBackColorAndPat(&backColor);
|
|
} else {
|
|
GetBackColor(&backColor);
|
|
}
|
|
|
|
offscreenGWorld = nil;
|
|
if((**docInfo).flags.offscreenBitMap && !(**(**docInfo).globals).flags.progressLoopCalled && !(**(**docInfo).globals).savedGWorld && !EmptyRgn(newClip)) {
|
|
savedGWorld = GetGlobalGWorld((**docInfo).globals);
|
|
if(savedGWorld != nil) {
|
|
DI_MEMCANTFAIL(docInfo);
|
|
GetPortRect(&drawRect);
|
|
LocalToGlobalRect(&drawRect);
|
|
pixMap = GetGWorldPixMap(savedGWorld);
|
|
if(QDError() == noErr) {
|
|
gFlags = GetPixelsState(pixMap);
|
|
NoPurgePixels(pixMap);
|
|
if(QDError() == noErr) {
|
|
if(!(UpdateGWorld(&savedGWorld, 0, &drawRect, nil, nil, 0) & gwFlagErr)) {
|
|
tempPixMap = GetGWorldPixMap(savedGWorld);
|
|
if(QDError() == noErr) {
|
|
pixMap = tempPixMap;
|
|
(**(**docInfo).globals).offscreenGWorld = savedGWorld;
|
|
if(LockPixels(pixMap)) {
|
|
offscreenGWorld = savedGWorld;
|
|
GetGWorld(&savedGWorld, &savedGDevice);
|
|
SetGWorld(offscreenGWorld, nil);
|
|
SetClip(newClip);
|
|
RGBBackColorAndPat(&backColor);
|
|
(**(**docInfo).globals).savedGWorld = savedGWorld;
|
|
} else {
|
|
goto ResetPixels;
|
|
}
|
|
}
|
|
} else {
|
|
ResetPixels :
|
|
SetPixelsState(pixMap, gFlags);
|
|
}
|
|
}
|
|
}
|
|
DI_MEMCANFAIL(docInfo);
|
|
}
|
|
}
|
|
|
|
/* Erase the area in which to draw */
|
|
if(!((**docInfo).flags.drawWithoutErase) && ((**docInfo).printData == nil)) {
|
|
EraseRgn(newClip);
|
|
}
|
|
|
|
/* Save the bounds rectangle for drawing purposes */
|
|
GetRegionBounds(newClip,&drawRect);
|
|
|
|
PenAndColorNormal();
|
|
|
|
/* Find the first line that appears in the drawRect */
|
|
errCode = FindFirstVisibleLine(docInfo, &lineInfo, drawRect.top);
|
|
if(errCode == errOffsetIsOutsideOfView) {
|
|
errCode = noErr;
|
|
}
|
|
|
|
if((errCode == noErr) && (lineInfo.paraIndex >= 0L)) {
|
|
|
|
paraIndex = lineInfo.paraIndex;
|
|
lineIndex = lineInfo.lineIndex;
|
|
curV = lineInfo.vPosition;
|
|
|
|
/* Loop through the the paragraphs until the bottom of the drawing rect */
|
|
for(; (paraIndex < (**docInfo).paraCount) && (curV < drawRect.bottom) && (errCode == noErr); ++paraIndex) {
|
|
|
|
/* If the height hasn't been calculated, get it */
|
|
errCode = CheckParagraphMeasure(docInfo, paraIndex, true);
|
|
|
|
if(errCode == noErr) {
|
|
/* Get the line starts for this paragraph */
|
|
lineStarts = (**(**docInfo).paraArray[paraIndex].paraInfo).lineStarts;
|
|
|
|
hState = HGetState((Handle)lineStarts);
|
|
HNoPurge((Handle)lineStarts);
|
|
|
|
/* Count the lines in the paragraph */
|
|
lineCount = InlineGetHandleSize((Handle)lineStarts) / sizeof(LSElement) - 1L;
|
|
|
|
/* If an empty paragraph, just draw whatever quote marks are needed */
|
|
if((lineIndex == 0L) && (lineIndex >= lineCount) && (curV < drawRect.bottom) && (errCode == noErr) && !(**docInfo).flags.drawDebugSymbols) {
|
|
/* Make sure lineRect is empty so it won't try to draw an empty line */
|
|
lineRect.left = lineRect.right = 0;
|
|
goto JustDrawQuotes;
|
|
}
|
|
|
|
/* Loop through the lines in the paragraph */
|
|
for(; lineIndex < lineCount && curV < drawRect.bottom && (errCode == noErr); ++lineIndex) {
|
|
|
|
/* Create a rectangle into which the text will be drawn */
|
|
|
|
/* Infinitely wide at first */
|
|
lineRect.left = SHRT_MIN;
|
|
lineRect.right = SHRT_MAX;
|
|
|
|
JustDrawQuotes :
|
|
/* Set the top to the top of the line */
|
|
lineRect.top = curV;
|
|
MoveTo((**docInfo).viewRect.left, curV);
|
|
|
|
DrawQuoteMarks(docInfo, paraIndex, (*lineStarts)[lineIndex].lsMeasure.height);
|
|
|
|
/* Move down the ascent to the base line */
|
|
curV += (*lineStarts)[lineIndex].lsMeasure.ascent;
|
|
Move(0, (*lineStarts)[lineIndex].lsMeasure.ascent);
|
|
|
|
/* Add the rest of the height to the current vertical position */
|
|
curV += (*lineStarts)[lineIndex].lsMeasure.height - (*lineStarts)[lineIndex].lsMeasure.ascent;
|
|
|
|
/* Set the bottom to the bottom of the line */
|
|
lineRect.bottom = curV;
|
|
|
|
/* Calculate where the drawing rectangle intersects the clipRgn */
|
|
RectRgn(scratchRgn, &lineRect);
|
|
SectRgn(newClip, scratchRgn, scratchRgn);
|
|
GetRegionBounds(scratchRgn,&lineRect);
|
|
|
|
if(!EmptyRect(&lineRect)) {
|
|
|
|
/* Layout the line to draw */
|
|
lineCache.lineIndex = lineIndex;
|
|
lineCache.paraIndex = paraIndex;
|
|
errCode = GetLineLayout(docInfo, &lineCache);
|
|
|
|
/* Draw the current line on the screen */
|
|
if(errCode == noErr) {
|
|
if(lineIndex == 0L) {
|
|
DrawListBullet(docInfo, paraIndex, lineCache.leftPosition, (*lineStarts)[lineIndex].lsMeasure.ascent);
|
|
}
|
|
|
|
errCode = RenderLine(docInfo, &lineCache, &lineRect, newClip, offscreenGWorld != nil);
|
|
}
|
|
}
|
|
}
|
|
|
|
HSetState((Handle)lineStarts, hState);
|
|
|
|
}
|
|
|
|
if(((**docInfo).flags.drawDebugSymbols) && (lineIndex == lineCount)) {
|
|
Move(3,0);
|
|
Line(0,-5);
|
|
Line(-2,0);
|
|
Line(0,2);
|
|
Line(3,0);
|
|
Line(0,-2);
|
|
Line(0,5);
|
|
}
|
|
|
|
if(lineCount <= 0L) {
|
|
curV += (**docInfo).paraArray[paraIndex].paraHeight;
|
|
}
|
|
|
|
/* Reset to the first line in the paragraph */
|
|
lineIndex = 0L;
|
|
}
|
|
}
|
|
|
|
PenAndColorNormal();
|
|
|
|
if(offscreenGWorld != nil) {
|
|
SetGWorld(savedGWorld, savedGDevice);
|
|
if(errCode == noErr) {
|
|
RGBColor blackColor /* = {0,0,0} */, whiteColor /* = {0xffff,0xffff,0xffff} */;
|
|
|
|
blackColor.red = blackColor.green = blackColor.blue = 0;
|
|
whiteColor.red = whiteColor.green = whiteColor.blue = 0xffff;
|
|
|
|
GetRegionBounds(newClip,&drawRect);
|
|
RGBForeColor(&blackColor);
|
|
RGBBackColorAndPat(&whiteColor);
|
|
CopyBits(GetPortBitMapForCopyBits(offscreenGWorld),
|
|
GetPortBitMapForCopyBits(GetWindowPort((**docInfo).docWindow)),
|
|
&drawRect, &drawRect, srcCopy, newClip);
|
|
errCode = QDError();
|
|
RGBBackColorAndPat(&backColor);
|
|
}
|
|
SetPixelsState(pixMap, gFlags);
|
|
(**(**docInfo).globals).savedGWorld = nil;
|
|
}
|
|
|
|
if(errCode == noErr) {
|
|
/* If the caret was on before drawing started, leave it on and redraw the caret */
|
|
if((**docInfo).flags.caretOn) {
|
|
(**docInfo).flags.caretOn = false;
|
|
DrawCaret(docInfo, nil);
|
|
}
|
|
|
|
/* Redraw the selection region */
|
|
if((**docInfo).flags.selectionDirty) {
|
|
DiffRgn((**docInfo).hiliteRgn, newClip, (**docInfo).hiliteRgn);
|
|
CalcSelectionRgn(docInfo, preserveLine);
|
|
} else {
|
|
InvertSelection(docInfo);
|
|
}
|
|
}
|
|
|
|
DisposeRgn(newClip);
|
|
SetClip(oldClip);
|
|
DisposeRgn(oldClip);
|
|
|
|
if((errCode != noErr) && (errCode != cantDoThatInCurrentMode) && ((**docInfo).flags.offscreenBitMap)) {
|
|
(**docInfo).flags.offscreenBitMap = false;
|
|
errCode = DrawDocument(docInfo, clipRgn, preserveLine);
|
|
(**docInfo).flags.offscreenBitMap = true;
|
|
|
|
} else if(errCode == noErr) {
|
|
|
|
/* If the scrolls are dirty, reset and redraw them */
|
|
if((**docInfo).flags.scrollsDirty) {
|
|
ResetScrollbars(docInfo);
|
|
/* If this is in response to an update event, redraw the scrolls */
|
|
} else if((clipRgn == nil) || ((**docInfo).flags.drawWithoutErase)) {
|
|
DI_MEMCANTFAIL(docInfo);
|
|
GetVisibleRgn(scratchRgn);
|
|
if((**docInfo).vScroll != nil) {
|
|
#ifndef SHOWHIDESCROLLS
|
|
Update1Control((**docInfo).vScroll, scratchRgn);
|
|
#else
|
|
GetControlRect((**docInfo).vScroll, &drawRect);
|
|
if(((**docInfo).flags.scrollsVisible) && (drawRect.bottom - drawRect.top >= kTooSmallForScroll)) {
|
|
ShowControl((**docInfo).vScroll);
|
|
Update1Control((**docInfo).vScroll, scratchRgn);
|
|
} else {
|
|
if(!((**docInfo).flags.drawWithoutErase)) {
|
|
HideControl((**docInfo).vScroll);
|
|
EraseRect(&drawRect);
|
|
}
|
|
FrameRect(&drawRect);
|
|
}
|
|
#endif
|
|
}
|
|
if((**docInfo).hScroll != nil) {
|
|
#ifndef SHOWHIDESCROLLS
|
|
Update1Control((**docInfo).hScroll, scratchRgn);
|
|
#else
|
|
GetControlRect((**docInfo).hScroll, &drawRect);
|
|
if(((**docInfo).flags.scrollsVisible) && (drawRect.right - drawRect.left >= kTooSmallForScroll)) {
|
|
ShowControl((**docInfo).hScroll);
|
|
Update1Control((**docInfo).hScroll, scratchRgn);
|
|
} else {
|
|
if(!((**docInfo).flags.drawWithoutErase)) {
|
|
HideControl((**docInfo).hScroll);
|
|
EraseRect(&drawRect);
|
|
}
|
|
FrameRect(&drawRect);
|
|
}
|
|
#endif
|
|
}
|
|
DI_MEMCANFAIL(docInfo);
|
|
}
|
|
}
|
|
|
|
ResetPortInfo(&savedPortInfo);
|
|
|
|
return errCode;
|
|
}
|
|
|
|
/* Draw the line of text */
|
|
OSErr RenderLine(DocumentInfoHandle docInfo, LayoutCachePtr lineCache, Rect *drawRect, RgnHandle drawRgn, Boolean offscreen)
|
|
{
|
|
OrderHandle orderingHndl;
|
|
ParagraphInfoHandle paraInfo;
|
|
GraphicInfoHandle graphicInfo;
|
|
short numRuns, runIndex, curDirection, leftWS, rightWS;
|
|
JustStyleCode styleRunPosition;
|
|
Byte hState;
|
|
LongSTElement tempStyle;
|
|
Point scaling, penLoc;
|
|
short hPosition;
|
|
PicHandle thePict;
|
|
Rect pictRect;
|
|
OSErr errCode;
|
|
long handleSize;
|
|
RgnHandle scratchRgn;
|
|
Style tabFace;
|
|
Boolean ws = false;
|
|
|
|
scratchRgn = (**(**docInfo).globals).scratchRgn;
|
|
paraInfo = (**docInfo).paraArray[lineCache->paraIndex].paraInfo;
|
|
hPosition = (**docInfo).hPosition - lineCache->leftPosition;
|
|
orderingHndl = lineCache->orderingHndl;
|
|
handleSize = InlineGetHandleSize((Handle)orderingHndl);
|
|
if(handleSize < 0L) {
|
|
return handleSize;
|
|
}
|
|
numRuns = handleSize / sizeof(OrderEntry);
|
|
|
|
for(leftWS = runIndex = 0; runIndex < numRuns; ++runIndex) {
|
|
if((*orderingHndl)[runIndex].isWhitespace) {
|
|
++leftWS;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for(rightWS = 0, runIndex = numRuns; --runIndex >= 0; ) {
|
|
if((*orderingHndl)[runIndex].isWhitespace) {
|
|
++rightWS;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Not really necessary for un-justified text */
|
|
styleRunPosition = (numRuns == 1) ? onlyStyleRun : leftStyleRun;
|
|
|
|
/* Initialize scaling factors to 1:1 */
|
|
scaling.h = scaling.v = 1;
|
|
|
|
/* Go through all of the style runs to draw them from left to right */
|
|
for(errCode = noErr, runIndex = 0; errCode == noErr && runIndex < numRuns && (GetPen(&penLoc), penLoc.h < drawRect->right) && ((**docInfo).flags.drawDebugSymbols || numRuns - runIndex > rightWS); ++runIndex, --leftWS) {
|
|
|
|
/* If the current location is scrolled out of view, just move over */
|
|
if((hPosition > 0L) || (!(**docInfo).flags.drawDebugSymbols && (leftWS > 0))) {
|
|
|
|
hPosition -= (*orderingHndl)[runIndex].width;
|
|
|
|
/* If some is visible, move left to the starting drawing location */
|
|
if((hPosition < 0L) && (leftWS <= 0)) {
|
|
Move(-(((*orderingHndl)[runIndex].width + hPosition)), 0);
|
|
hPosition = 0L;
|
|
|
|
/* Repeat this run */
|
|
--runIndex;
|
|
++leftWS;
|
|
continue;
|
|
} else {
|
|
/* Go on to the next run */
|
|
goto NextRun;
|
|
}
|
|
}
|
|
|
|
/* If the current location is in the middle, move over to it */
|
|
if(hPosition < 0L) {
|
|
penLoc.h -= hPosition;
|
|
hPosition = 0L;
|
|
|
|
/* If the location is beyond the right side, there's nothing to draw */
|
|
if(penLoc.h > drawRect->right)
|
|
break;
|
|
|
|
/* Move the pen over */
|
|
MoveTo(penLoc.h, penLoc.v);
|
|
}
|
|
|
|
/* Calculate where the pen will be after drawing occurs */
|
|
penLoc.h += (*orderingHndl)[runIndex].width;
|
|
|
|
/* If it's not in the visible drawing area, just move the pen over */
|
|
if(penLoc.h < drawRect->left) {
|
|
MoveTo(penLoc.h, penLoc.v);
|
|
|
|
/* Go on to the next run */
|
|
goto NextRun;
|
|
}
|
|
|
|
GetStyle(&tempStyle, (**docInfo).theStyleTable, (*orderingHndl)[runIndex].styleIndex);
|
|
|
|
/* Is this text or a graphic? */
|
|
if(!((*orderingHndl)[runIndex].isGraphic)) {
|
|
|
|
/* It's text, so set the text style */
|
|
SetTextStyleWithDefaults(nil, docInfo, &tempStyle.stInfo.textStyle, true, ((**docInfo).printData != nil));
|
|
TextMode(srcOr);
|
|
|
|
/* Set direction and lock the text */
|
|
curDirection = GetSysDirection();
|
|
SetSysDirection((**paraInfo).direction);
|
|
|
|
/* If it's a tab and the paragraph isn't centered, draw the tab */
|
|
if(((*orderingHndl)[runIndex].isTab) && ((**paraInfo).justification != teCenter)) {
|
|
tabFace = GetPortFace() & (Byte)GetScriptVariable(smCurrentScript, smScriptValidStyles);
|
|
if((tabFace & underline) && (leftWS <= 0)) {
|
|
if(tabFace & (outline | shadow)) {
|
|
MoveTo(penLoc.h - 1, penLoc.v);
|
|
Line(-(*orderingHndl)[runIndex].width + 1, 0);
|
|
}
|
|
Move(0, (tabFace & (outline | shadow)) ? 2 : 1);
|
|
Line((*orderingHndl)[runIndex].width - 1, 0);
|
|
Move(1, (tabFace & (outline | shadow)) ? -2 : -1);
|
|
if(tabFace & shadow) {
|
|
Move(-1, 3);
|
|
Line(-(*orderingHndl)[runIndex].width + 1, 0);
|
|
if(tabFace & outline) {
|
|
Move(0, 1);
|
|
Line((*orderingHndl)[runIndex].width - 1, 0);
|
|
Move(1, -4);
|
|
} else {
|
|
Move((*orderingHndl)[runIndex].width, -3);
|
|
}
|
|
}
|
|
} else {
|
|
Move((*orderingHndl)[runIndex].width, 0);
|
|
}
|
|
} else if((*orderingHndl)[runIndex].len > 0) {
|
|
long offset, len;
|
|
|
|
hState = HGetState((Handle)(**docInfo).theText);
|
|
HLock((Handle)(**docInfo).theText);
|
|
|
|
offset = (*orderingHndl)[runIndex].offset - (**docInfo).textOffset;
|
|
len = (*orderingHndl)[runIndex].len;
|
|
if(GetPortFace() & underline) {
|
|
Boolean leftToRight;
|
|
|
|
leftToRight = !(Byte)GetScriptVariable(smCurrentScript, smScriptRight);
|
|
if(leftWS == 0) {
|
|
if(leftToRight) {
|
|
long leadWS;
|
|
|
|
IsWhitespace(*(**docInfo).theText + offset, len, smCurrentScript, (**(**docInfo).globals).whitespaceGlobals, &leadWS);
|
|
if(leadWS != 0L) {
|
|
Move(TextWidth(*(**docInfo).theText + offset, 0, leadWS), 0);
|
|
len -= leadWS;
|
|
offset += leadWS;
|
|
}
|
|
} else if(len != (*orderingHndl)[runIndex].rightLen) {
|
|
len = (*orderingHndl)[runIndex].rightLen;
|
|
Move((*orderingHndl)[runIndex].width - (*orderingHndl)[runIndex].rightWidth, 0);
|
|
}
|
|
}
|
|
if((styleRunPosition == onlyStyleRun) || (styleRunPosition == rightStyleRun) || (rightWS - 1 == numRuns - runIndex)) {
|
|
long trailWS;
|
|
|
|
if(!leftToRight) {
|
|
IsWhitespace(*(**docInfo).theText + offset, len, smCurrentScript, (**(**docInfo).globals).whitespaceGlobals, &trailWS);
|
|
if(trailWS != 0L) {
|
|
len -= trailWS;
|
|
offset += trailWS;
|
|
ws = true;
|
|
}
|
|
} else {
|
|
trailWS = (*orderingHndl)[runIndex].len - (*orderingHndl)[runIndex].leftLen;
|
|
if(trailWS != 0L) {
|
|
len -= trailWS;
|
|
ws = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Simply draw the text */
|
|
DrawJustified((Ptr)*(**docInfo).theText + offset, len, 0L, styleRunPosition, scaling, scaling);
|
|
|
|
if((**docInfo).flags.drawDebugSymbols) {
|
|
if(((Ptr)*(**docInfo).theText + (((*orderingHndl)[runIndex].offset - (**docInfo).textOffset)))[(*orderingHndl)[runIndex].len - 1L] == kCarriageReturnChar) {
|
|
Move(2,-2);
|
|
Line(0,1);
|
|
Line(-1,-1);
|
|
Line(1,-1);
|
|
Line(0,1);
|
|
Line(2,0);
|
|
Line(0,-2);
|
|
Move(1,4);
|
|
}
|
|
}
|
|
|
|
HSetState((Handle)(**docInfo).theText, hState);
|
|
}
|
|
|
|
SetSysDirection(curDirection);
|
|
|
|
} else {
|
|
if((graphicInfo = tempStyle.stInfo.graphicStyle.graphicInfo) != nil) {
|
|
|
|
/* Call the routine to draw the graphic */
|
|
if((**graphicInfo).itemProc == nil) {
|
|
thePict = (**(PictGraphicInfoHandle)graphicInfo).pict;
|
|
pictRect = (**thePict).picFrame;
|
|
OffsetRect(&pictRect, penLoc.h - pictRect.right, penLoc.v - pictRect.bottom);
|
|
DrawPicture(thePict, &pictRect);
|
|
} else {
|
|
errCode = CallGraphic(docInfo, graphicInfo, (*orderingHndl)[runIndex].offset, peGraphicDraw, &tempStyle.stInfo.graphicStyle);
|
|
if(errCode == noErr) {
|
|
SetEmptyRgn(scratchRgn);
|
|
CallGraphic(docInfo, graphicInfo, (*orderingHndl)[runIndex].offset, peGraphicRegion, scratchRgn);
|
|
UnionRgn(scratchRgn, (**docInfo).graphicRgn, (**docInfo).graphicRgn);
|
|
if((**graphicInfo).drawInWindow && offscreen) {
|
|
DiffRgn(drawRgn, scratchRgn, drawRgn);
|
|
}
|
|
}
|
|
SetClip(drawRgn);
|
|
}
|
|
}
|
|
|
|
MoveTo(penLoc.h, penLoc.v);
|
|
}
|
|
NextRun :
|
|
styleRunPosition = (runIndex == numRuns - 2) ? rightStyleRun : middleStyleRun;
|
|
}
|
|
|
|
if((!(**docInfo).paraArray[lineCache->paraIndex].paraLSDirty) &&
|
|
((**paraInfo).lineStarts != nil) &&
|
|
(*(**paraInfo).lineStarts != nil)) {
|
|
(*(**paraInfo).lineStarts)[lineCache->lineIndex].lsULFlag = (ws || rightWS != 0);
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
OSErr RedrawParagraph(DocumentInfoHandle docInfo, long paraIndex, long startChar, long endChar, LSTable oldLineStarts)
|
|
{
|
|
LSTable lineStarts;
|
|
long lineCount, oldLineCount, firstDiffLine, oldNextSameLine, newNextSameLine;
|
|
PETEPortInfo savedPortInfo;
|
|
long topDiffPosition, oldScrollPosition, newScrollPosition, windowHeight, scrollDistance, vPosition;
|
|
Rect tempRect;
|
|
RgnHandle tempRgn;
|
|
OSErr errCode;
|
|
Byte hState;
|
|
|
|
errCode = ParagraphPosition(docInfo, paraIndex, &vPosition);
|
|
if(errCode == noErr) {
|
|
errCode = ReflowParagraph(docInfo, paraIndex, startChar, endChar);
|
|
}
|
|
if(errCode != noErr) {
|
|
if(errCode == cantDoThatInCurrentMode) {
|
|
InvalidateDocument(docInfo, true);
|
|
}
|
|
SetParaDirty(docInfo, paraIndex);
|
|
return errCode;
|
|
}
|
|
topDiffPosition = oldScrollPosition = newScrollPosition = vPosition;
|
|
|
|
lineStarts = (**(**docInfo).paraArray[paraIndex].paraInfo).lineStarts;
|
|
hState = HGetState((Handle)lineStarts);
|
|
HNoPurge((Handle)lineStarts);
|
|
|
|
lineCount = InlineGetHandleSize((Handle)lineStarts) / sizeof(LSElement) - 1L;
|
|
oldLineCount = InlineGetHandleSize((Handle)oldLineStarts) / sizeof(LSElement) - 1L;
|
|
|
|
for(firstDiffLine = 0L;
|
|
(firstDiffLine < lineCount) &&
|
|
(firstDiffLine < oldLineCount) &&
|
|
(startChar > (*oldLineStarts)[firstDiffLine + 1L].lsStartChar) &&
|
|
((*lineStarts)[firstDiffLine + 1L].lsStartChar == (*oldLineStarts)[firstDiffLine + 1L].lsStartChar);
|
|
++firstDiffLine) {
|
|
|
|
;
|
|
}
|
|
|
|
for(oldNextSameLine = oldLineCount, newNextSameLine = lineCount;
|
|
(oldNextSameLine > 0L) &&
|
|
(newNextSameLine > 0L) &&
|
|
(endChar < (*lineStarts)[newNextSameLine - 1L].lsStartChar) &&
|
|
(endChar < (*oldLineStarts)[oldNextSameLine - 1L].lsStartChar) &&
|
|
((*lineStarts)[newNextSameLine - 1L].lsStartChar == (*oldLineStarts)[oldNextSameLine - 1L].lsStartChar);
|
|
--oldNextSameLine, --newNextSameLine) {
|
|
|
|
;
|
|
}
|
|
|
|
if(firstDiffLine != 0L) {
|
|
topDiffPosition += ResetLineCache((**docInfo).paraArray[paraIndex].paraInfo, firstDiffLine);
|
|
}
|
|
topDiffPosition -= (**docInfo).vPosition;
|
|
|
|
if(oldNextSameLine > firstDiffLine) {
|
|
oldScrollPosition += (**(**docInfo).paraArray[paraIndex].paraInfo).lineStartCacheHeight;
|
|
}
|
|
oldScrollPosition += LineHeights(oldLineStarts, (oldNextSameLine > firstDiffLine) ? firstDiffLine : 0L, oldNextSameLine) - (**docInfo).vPosition;
|
|
|
|
if(newNextSameLine != 0L) {
|
|
newScrollPosition += ResetLineCache((**docInfo).paraArray[paraIndex].paraInfo, newNextSameLine);
|
|
}
|
|
newScrollPosition -= (**docInfo).vPosition;
|
|
|
|
HSetState((Handle)lineStarts, hState);
|
|
|
|
windowHeight = RectHeight(&(**docInfo).viewRect);
|
|
|
|
if(topDiffPosition >= windowHeight) {
|
|
return noErr;
|
|
}
|
|
|
|
if(topDiffPosition < 0L) {
|
|
topDiffPosition = 0L;
|
|
}
|
|
|
|
scrollDistance = newScrollPosition - oldScrollPosition;
|
|
|
|
if((oldScrollPosition < 0L) && (newScrollPosition < 0L)) {
|
|
(**docInfo).vPosition += scrollDistance;
|
|
return noErr;
|
|
}
|
|
|
|
if(oldScrollPosition < 0L) {
|
|
oldScrollPosition = 0L;
|
|
}
|
|
|
|
if(newScrollPosition < 0L) {
|
|
newScrollPosition = 0L;
|
|
}
|
|
|
|
tempRgn = NewRgn();
|
|
if(tempRgn == nil) {
|
|
return memFullErr;
|
|
}
|
|
|
|
/* Save old port info */
|
|
SavePortInfo(GetWindowPort((**docInfo).docWindow), &savedPortInfo);
|
|
|
|
tempRect = (**docInfo).viewRect;
|
|
if(oldScrollPosition < windowHeight) {
|
|
tempRect.top += (oldScrollPosition < newScrollPosition) ? oldScrollPosition : newScrollPosition;
|
|
if(scrollDistance != 0) {
|
|
ScrollRectInDoc(docInfo, &tempRect, 0, scrollDistance, tempRgn);
|
|
}
|
|
} else {
|
|
tempRect.top += newScrollPosition;
|
|
RectRgn(tempRgn, &tempRect);
|
|
}
|
|
|
|
tempRect = (**docInfo).viewRect;
|
|
tempRect.top += topDiffPosition;
|
|
if(newScrollPosition < windowHeight) {
|
|
tempRect.bottom = (**docInfo).viewRect.top + newScrollPosition;
|
|
}
|
|
if(!EmptyRect(&tempRect)) {
|
|
RectAndRgn(tempRgn, (**(**docInfo).globals).scratchRgn, &tempRect);
|
|
}
|
|
|
|
DiffRgn((**docInfo).hiliteRgn, tempRgn, (**docInfo).hiliteRgn);
|
|
DiffRgn((**docInfo).graphicRgn, tempRgn, (**docInfo).graphicRgn);
|
|
(**docInfo).flags.selectionDirty = true;
|
|
|
|
errCode = DrawDocument(docInfo, tempRgn, false);
|
|
|
|
DisposeRgn(tempRgn);
|
|
|
|
ResetPortInfo(&savedPortInfo);
|
|
|
|
return errCode;
|
|
|
|
}
|
|
|
|
OSErr RedrawDocument(DocumentInfoHandle docInfo, long textOffset)
|
|
{
|
|
SelData selection;
|
|
RgnHandle clipRgn;
|
|
long rectHeight;
|
|
Rect viewRect;
|
|
OSErr errCode;
|
|
|
|
selection.paraIndex = ParagraphIndex(docInfo, textOffset);
|
|
selection.offset = textOffset;
|
|
selection.lastLine = (textOffset != 0L);
|
|
errCode = OffsetToVPosition(docInfo, &selection, false);
|
|
if(errCode != noErr) {
|
|
if(errCode == cantDoThatInCurrentMode) {
|
|
InvalidateDocument(docInfo, true);
|
|
}
|
|
return errCode;
|
|
}
|
|
viewRect = (**docInfo).viewRect;
|
|
selection.vPosition -= (**docInfo).vPosition;
|
|
rectHeight = RectHeight(&viewRect);
|
|
if(selection.vPosition < rectHeight) {
|
|
if(selection.vPosition > 0L) {
|
|
viewRect.top += selection.vPosition;
|
|
}
|
|
|
|
clipRgn = NewRgn();
|
|
if(clipRgn != nil) {
|
|
RectRgn(clipRgn, &viewRect);
|
|
DiffRgn((**docInfo).hiliteRgn, clipRgn, (**docInfo).hiliteRgn);
|
|
(**docInfo).flags.selectionDirty = true;
|
|
errCode = DrawDocument(docInfo, clipRgn, false);
|
|
DisposeRgn(clipRgn);
|
|
} else {
|
|
errCode = memFullErr;
|
|
}
|
|
} else {
|
|
errCode = noErr;
|
|
}
|
|
|
|
if(errCode == cantDoThatInCurrentMode) {
|
|
InvalidateDocument(docInfo, true);
|
|
}
|
|
return errCode;
|
|
}
|
|
|
|
OSErr ScrollAndDrawDocument(DocumentInfoHandle docInfo, long vPosition, long distance)
|
|
{
|
|
long rectHeight;
|
|
Rect viewRect;
|
|
short position, scrollDistance;
|
|
PETEPortInfo savedPortInfo;
|
|
RgnHandle clipRgn;
|
|
OSErr errCode;
|
|
|
|
viewRect = (**docInfo).viewRect;
|
|
rectHeight= RectHeight(&viewRect);
|
|
vPosition -= (**docInfo).vPosition;
|
|
if(vPosition >= rectHeight) {
|
|
return noErr;
|
|
}
|
|
if(vPosition > 0L) {
|
|
position = vPosition;
|
|
if(distance > 0L) {
|
|
viewRect.top += position;
|
|
} else {
|
|
viewRect.bottom = viewRect.top + position;
|
|
}
|
|
}
|
|
|
|
scrollDistance = distance;
|
|
if(scrollDistance != 0) {
|
|
clipRgn = NewRgn();
|
|
if(clipRgn != nil) {
|
|
SavePortInfo(GetWindowPort((**docInfo).docWindow), &savedPortInfo);
|
|
ScrollRectInDoc(docInfo, &viewRect, 0, scrollDistance, clipRgn);
|
|
errCode = DrawDocument(docInfo, clipRgn, false);
|
|
DisposeRgn(clipRgn);
|
|
ResetPortInfo(&savedPortInfo);
|
|
} else {
|
|
errCode = memFullErr;
|
|
}
|
|
} else {
|
|
errCode = noErr;
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
void EraseCaret(DocumentInfoHandle docInfo)
|
|
{
|
|
if((**docInfo).flags.caretOn) {
|
|
DrawCaret(docInfo, nil);
|
|
}
|
|
}
|
|
|
|
void DrawCaret(DocumentInfoHandle docInfo, SelDataPtr selection)
|
|
{
|
|
short hFixedPrimary, hFixedSecondary;
|
|
long vWideTop, vWideMiddle, vWideBottom, windowHeight;
|
|
Rect viewRect;
|
|
PETEPortInfo savedPortInfo;
|
|
short vTop, vMiddle, vBottom, hPrimary, hSecondary;
|
|
RgnHandle scratchRgn;
|
|
SelData tempSelection;
|
|
|
|
if(selection == nil) {
|
|
tempSelection = (**docInfo).selStart;
|
|
selection = &tempSelection;
|
|
}
|
|
|
|
viewRect = (**docInfo).viewRect;
|
|
vWideTop = selection->vPosition;
|
|
vWideTop -= (**docInfo).vPosition;
|
|
vWideTop += 1;
|
|
vWideBottom = vWideMiddle = vWideTop;
|
|
vWideMiddle += selection->vLineHeight >> 1;
|
|
vWideBottom += selection->vLineHeight;
|
|
|
|
windowHeight = RectHeight(&viewRect);
|
|
|
|
if((vWideBottom < 0L) || (vWideTop >= windowHeight)) {
|
|
return;
|
|
}
|
|
|
|
hFixedPrimary = selection->lPosition - (**docInfo).hPosition;
|
|
hFixedSecondary = selection->rPosition - (**docInfo).hPosition;
|
|
if((**(**docInfo).paraArray[selection->paraIndex].paraInfo).direction != leftCaret) {
|
|
Exchange(hFixedPrimary, hFixedSecondary);
|
|
}
|
|
|
|
if(!(GetScriptManagerVariable(smGenFlags) & (1L << smfDualCaret))) {
|
|
if(((**(**docInfo).paraArray[selection->paraIndex].paraInfo).direction != leftCaret) ==
|
|
(!(Boolean)GetScriptVariable((short)GetScriptManagerVariable(smKeyScript), smScriptRight))) {
|
|
hFixedPrimary = hFixedSecondary;
|
|
} else {
|
|
hFixedSecondary = hFixedPrimary;
|
|
}
|
|
}
|
|
|
|
|
|
hPrimary = hFixedPrimary - 1 + viewRect.left;
|
|
hSecondary = hFixedSecondary - 1 + viewRect.left;
|
|
vTop = vWideTop - 1 + viewRect.top;
|
|
vMiddle = vWideMiddle - 1 + viewRect.top;
|
|
vBottom = vWideBottom - 1 + viewRect.top;
|
|
|
|
SavePortInfo(GetWindowPort((**docInfo).docWindow), &savedPortInfo);
|
|
scratchRgn = (**(**docInfo).globals).scratchRgn;
|
|
GetClip(scratchRgn);
|
|
ClipRect(&viewRect);
|
|
|
|
PenAndColorNormal();
|
|
PenMode(patXor);
|
|
|
|
if((hPrimary > viewRect.left) && (hPrimary < viewRect.right) && (vMiddle >= viewRect.top)) {
|
|
if(vTop < viewRect.top) {
|
|
vTop = viewRect.top;
|
|
}
|
|
if(vMiddle >= viewRect.bottom) {
|
|
vMiddle = viewRect.bottom - 1;
|
|
}
|
|
MoveTo(hPrimary, vTop);
|
|
LineTo(hPrimary, vMiddle);
|
|
}
|
|
if((hSecondary > viewRect.left) && (hSecondary < viewRect.right) && (vMiddle + 1 < viewRect.bottom)) {
|
|
if(vMiddle + 1 < viewRect.top) {
|
|
vMiddle = viewRect.top - 1;
|
|
}
|
|
if(vBottom >= viewRect.bottom) {
|
|
vBottom = viewRect.bottom - 1;
|
|
}
|
|
MoveTo(hSecondary, vMiddle + 1);
|
|
LineTo(hSecondary, vBottom);
|
|
}
|
|
|
|
SetClip(scratchRgn);
|
|
ResetPortInfo(&savedPortInfo);
|
|
|
|
if(selection == &tempSelection) {
|
|
(**docInfo).flags.caretOn = !(**docInfo).flags.caretOn;
|
|
}
|
|
|
|
}
|
|
|
|
void InvalidateDocument(DocumentInfoHandle docInfo, Boolean viewOnly)
|
|
{
|
|
PETEPortInfo savedPortInfo;
|
|
Rect tempRect;
|
|
|
|
if((**docInfo).printData == nil) {
|
|
tempRect = (viewOnly && !((**docInfo).flags.scrollsDirty)) ? (**docInfo).viewRect : (**docInfo).docRect;
|
|
if((**docInfo).flags.recalcOff) {
|
|
RectAndRgn((**docInfo).updateRgn, (**(**docInfo).globals).scratchRgn, &tempRect);
|
|
} else {
|
|
SavePortInfo(GetWindowPort((**docInfo).docWindow), &savedPortInfo);
|
|
InvalWindowRect((**docInfo).docWindow,&tempRect);
|
|
ResetPortInfo(&savedPortInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
void InvalidateDocUpdate(DocumentInfoHandle docInfo)
|
|
{
|
|
PETEPortInfo savedPortInfo;
|
|
|
|
if(!EmptyRgn((**docInfo).updateRgn)) {
|
|
SavePortInfo(((**docInfo).printData == nil) ? GetWindowPort((**docInfo).docWindow) : (**(**docInfo).printData).pPort, &savedPortInfo);
|
|
InvalWindowRgn((**docInfo).docWindow,(**docInfo).updateRgn);
|
|
ResetPortInfo(&savedPortInfo);
|
|
SetEmptyRgn((**docInfo).updateRgn);
|
|
}
|
|
}
|
|
|
|
OSErr CreateDocPict(DocumentInfoHandle docInfo, PicHandle *thePic)
|
|
{
|
|
PicHandle newPic;
|
|
OpenCPicParams picHeader;
|
|
OSErr errCode;
|
|
PETEPortInfo savedPortInfo;
|
|
RgnHandle oldVisRgn, oldClipRgn, tempRgn;
|
|
DocFlagsBlock flags;
|
|
|
|
errCode = memFullErr;
|
|
tempRgn = NewRgn();
|
|
if(tempRgn == nil) {
|
|
goto JustReturn;
|
|
}
|
|
|
|
oldVisRgn = NewRgn();
|
|
if(oldVisRgn == nil) {
|
|
goto DisposeTemp;
|
|
}
|
|
|
|
oldClipRgn = NewRgn();
|
|
if(oldVisRgn == nil) {
|
|
goto DisposeVis;
|
|
}
|
|
|
|
SavePortInfo(GetWindowPort((**docInfo).docWindow), &savedPortInfo);
|
|
|
|
EraseCaret(docInfo);
|
|
|
|
picHeader.srcRect = (**docInfo).docRect;
|
|
picHeader.hRes = 0x00480000;
|
|
picHeader.vRes = 0x00480000;
|
|
picHeader.version = -2;
|
|
picHeader.reserved1 = 0L;
|
|
picHeader.reserved2 = 0L;
|
|
|
|
RectRgn(tempRgn, &picHeader.srcRect);
|
|
GetVisibleRgn(oldVisRgn);
|
|
GetClip(oldClipRgn);
|
|
SetVisibleRgn(tempRgn);
|
|
SetClip(tempRgn);
|
|
|
|
newPic = OpenCPicture(&picHeader);
|
|
|
|
if((errCode = QDError()) == noErr) {
|
|
flags = (**docInfo).flags;
|
|
|
|
(**docInfo).flags.offscreenBitMap = false;
|
|
(**docInfo).flags.scrollsVisible = false;
|
|
(**docInfo).flags.isActive = false;
|
|
(**docInfo).flags.scrollsDirty = false;
|
|
(**docInfo).flags.drawWithoutErase = true;
|
|
|
|
errCode = DrawDocument(docInfo, tempRgn, false);
|
|
|
|
(**docInfo).flags = flags;
|
|
|
|
ClosePicture();
|
|
}
|
|
|
|
SetClip(oldClipRgn);
|
|
SetVisibleRgn(oldVisRgn);
|
|
|
|
ResetPortInfo(&savedPortInfo);
|
|
|
|
DisposeRgn(oldClipRgn);
|
|
|
|
DisposeVis :
|
|
DisposeRgn(oldVisRgn);
|
|
|
|
DisposeTemp :
|
|
DisposeRgn(tempRgn);
|
|
|
|
JustReturn:
|
|
if(errCode == noErr) {
|
|
*thePic = newPic;
|
|
} else {
|
|
*thePic = nil;
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
OSErr DrawDocumentWithPicture(DocumentInfoHandle docInfo)
|
|
{
|
|
PETEPortInfo savedPortInfo;
|
|
Rect drawRect;
|
|
RGBColor backColor;
|
|
OSErr errCode;
|
|
|
|
/* Save old port info */
|
|
SavePortInfo(GetWindowPort((**docInfo).docWindow), &savedPortInfo);
|
|
|
|
backColor = DocOrGlobalBGColor(nil, docInfo);
|
|
if(!IsPETEDefaultColor(backColor)) {
|
|
RGBBackColorAndPat(&backColor);
|
|
}
|
|
drawRect = (**docInfo).docRect;
|
|
EraseRect(&drawRect);
|
|
DrawPicture((**(**docInfo).printData).docPic, &drawRect);
|
|
errCode = QDError();
|
|
|
|
ResetPortInfo(&savedPortInfo);
|
|
|
|
return errCode;
|
|
}
|
|
|
|
void DrawQuoteMarks(DocumentInfoHandle docInfo, long paraIndex, short lineHeight)
|
|
{
|
|
ParagraphInfoHandle paraInfo;
|
|
PenState curPen;
|
|
short hPosition, width, inset;
|
|
Byte quoteLevel, signedLevel;
|
|
Boolean rightToLeft;
|
|
Pattern gray,black;
|
|
|
|
paraInfo = (**docInfo).paraArray[paraIndex].paraInfo;
|
|
signedLevel = (**paraInfo).signedLevel;
|
|
quoteLevel = (**paraInfo).quoteLevel + signedLevel;
|
|
if(quoteLevel == 0) {
|
|
return;
|
|
}
|
|
|
|
rightToLeft = ((**(**docInfo).paraArray[paraIndex].paraInfo).direction != leftCaret);
|
|
hPosition = kDefaultMargin;
|
|
if(rightToLeft) {
|
|
hPosition = (**docInfo).docWidth - hPosition;
|
|
}
|
|
hPosition -= (**docInfo).hPosition;
|
|
|
|
GetPenState(&curPen);
|
|
PenAndColorNormal();
|
|
PenMode(patXor);
|
|
PenSize(2, 1);
|
|
if(signedLevel > 0) {
|
|
PenPat(GetQDGlobalsGray(&gray));
|
|
}
|
|
|
|
for(width = RectWidth(&(**docInfo).viewRect), inset = ((rightToLeft ? -kDefaultMargin : kDefaultMargin) * 2);
|
|
quoteLevel > 0 && hPosition >= 0L && hPosition < width;
|
|
hPosition += inset, --quoteLevel, --signedLevel) {
|
|
|
|
if(signedLevel == 0) {
|
|
PenPat(GetQDGlobalsBlack(&black));
|
|
}
|
|
MoveTo(hPosition + 1 + (**docInfo).viewRect.left, curPen.pnLoc.v);
|
|
Line(0, lineHeight - 1);
|
|
}
|
|
|
|
SetPenState(&curPen);
|
|
|
|
return;
|
|
}
|
|
|
|
void DrawOneChar(DocumentInfoHandle docInfo, StringPtr theChar)
|
|
{
|
|
PETEPortInfo savedPortInfo;
|
|
short vPosition;
|
|
SelData selection;
|
|
MyTextStyle textStyle;
|
|
Point penLoc;
|
|
Rect drawRect;
|
|
short hPosition;
|
|
LSTable lineStarts;
|
|
Boolean ws = false;
|
|
RGBColor backColor/* = {0xffff,0xffff,0xffff}*/;
|
|
|
|
SavePortInfo(GetWindowPort((**docInfo).docWindow), &savedPortInfo);
|
|
/* Stupid compiler */
|
|
backColor.red = backColor.green = backColor.blue = 0xffff;
|
|
backColor = DocOrGlobalBGColor(nil, docInfo);
|
|
if(!IsPETEDefaultColor(backColor)) {
|
|
RGBBackColorAndPat(&backColor);
|
|
} else {
|
|
GetBackColor(&backColor);
|
|
}
|
|
PenAndColorNormal();
|
|
GetCurrentTextStyle(docInfo, &textStyle);
|
|
SetTextStyleWithDefaults(nil, docInfo, &textStyle, true, false);
|
|
if(IsWhitespace(theChar + 1, theChar[0], smCurrentScript, (**(**docInfo).globals).whitespaceGlobals, nil)) {
|
|
Style face = GetPortFace();
|
|
if(face & underline) {
|
|
ws = true;
|
|
TextFace(face & ~underline);
|
|
}
|
|
}
|
|
TextMode(srcOr);
|
|
selection = (**docInfo).selStart;
|
|
lineStarts = (**(**docInfo).paraArray[selection.paraIndex].paraInfo).lineStarts;
|
|
(*lineStarts)[selection.lineIndex].lsULFlag = ws;
|
|
vPosition = (selection.vPosition - (**docInfo).vPosition) + (*lineStarts)[selection.lineIndex].lsMeasure.ascent;
|
|
hPosition = selection.lPosition - (**docInfo).hPosition + (**docInfo).viewRect.left;
|
|
MoveTo(hPosition, vPosition + (**docInfo).viewRect.top);
|
|
drawRect.top = (**docInfo).viewRect.top + (selection.vPosition - (**docInfo).vPosition);
|
|
drawRect.bottom = drawRect.top + (*lineStarts)[selection.lineIndex].lsMeasure.height;
|
|
drawRect.left = hPosition;
|
|
drawRect.right = hPosition + TextWidth(theChar, 1, theChar[0]);
|
|
EraseRect(&drawRect);
|
|
DrawText(theChar, 1, theChar[0]);
|
|
GetPen(&penLoc);
|
|
selection.hPosition = selection.rPosition = (selection.lPosition += (penLoc.h - hPosition));
|
|
(**docInfo).selStart = (**docInfo).selEnd = selection;
|
|
FlushDocInfoLineCache(docInfo);
|
|
PenAndColorNormal();
|
|
ResetPortInfo(&savedPortInfo);
|
|
}
|
|
|
|
void DrawListBullet(DocumentInfoHandle docInfo, long paraIndex, short leftPosition, short ascent)
|
|
{
|
|
ParagraphInfoHandle paraInfo;
|
|
short position, indentWidth;
|
|
PenState curPen;
|
|
Rect bullet;
|
|
short sAscent;
|
|
|
|
paraInfo = (**docInfo).paraArray[paraIndex].paraInfo;
|
|
if((**paraInfo).paraFlags & peListBits) {
|
|
position = (**docInfo).hPosition;
|
|
position -= leftPosition;
|
|
indentWidth = (((**paraInfo).tabCount == 0) ? (4 * kDefaultMargin) : ((**paraInfo).tabStops[0] / 3));
|
|
position += indentWidth;
|
|
if(position < 0L) {
|
|
GetPenState(&curPen);
|
|
indentWidth = FixMul(indentWidth, 0x0000C000 /* .75 */);
|
|
sAscent = (ascent > indentWidth ? indentWidth : ascent);
|
|
bullet.left = curPen.pnLoc.h - (position);
|
|
bullet.bottom = curPen.pnLoc.v - 1;
|
|
bullet.top = bullet.bottom - (sAscent - 4);
|
|
bullet.right = bullet.left + (sAscent - 4);
|
|
PenAndColorNormal();
|
|
PenMode(patXor);
|
|
switch((**paraInfo).paraFlags & peListBits) {
|
|
case peSquareList :
|
|
FrameRect(&bullet);
|
|
break;
|
|
case peCircleList :
|
|
FrameOval(&bullet);
|
|
break;
|
|
default :
|
|
PaintOval(&bullet);
|
|
}
|
|
SetPenState(&curPen);
|
|
}
|
|
}
|
|
}
|