home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-07-20 | 28.2 KB | 1,166 lines | [TEXT/MPCC] |
- // { WASTE PROJECT: }
- // { Unit Two: Creation & Destruction; Getting and Setting Variables &c. }
-
- // { Copyright © 1993-1994 Marco Piovanelli }
- // { All Rights Reserved }
-
- // C conversion by Dan Crevier
-
- #include "WASTEIntf.h"
- #include <Palettes.h>
- #include <QDOffscreen.h>
- #include <GestaltEqu.h>
-
- OSErr _WERegisterWithTSM(WEHandle hWE)
- {
- // { the WE record must be already locked }
- WEPtr pWE;
- OSType typeList[1];
- OSErr err;
-
- pWE = *hWE;
-
- // { do nothing if the Text Services Manager isn't available }
- if (BTST(pWE->flags, weFHasTextServices))
- {
- typeList[0] = kTextService;
- err = NewTSMDocument(1, typeList, &pWE->tsmReference, (long)hWE);
- if (err != noErr)
- {
- // { we don't consider it an error if our client application isn't TSM-aware }
- if (err != tsmNeverRegisteredErr)
- {
- goto cleanup;
- }
- }
- }
-
- // { clear result code }
- err = noErr;
-
- cleanup:
- // { return result code }
- return err;
- }
-
- pascal void WEStopInlineSession(WEHandle hWE)
- {
- TSMDocumentID tsmReference;
-
- tsmReference = (*hWE)->tsmReference;
- if (tsmReference != nil)
- {
- FixTSMDocument(tsmReference);
- }
- }
-
- pascal OSErr WENew(LongRect *destRect, LongRect *viewRect, short flags, WEHandle *hWE)
- {
- WEPtr pWE;
- short allocFlags;
- long weFlags;
- long response;
- Rect r;
- OSErr err;
-
- pWE = nil;
- weFlags = flags;
- allocFlags = kAllocClear;
-
- // { allocate the WE record }
- err = _WEAllocate(sizeof(WERec), allocFlags, (Handle *)hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { lock it down }
- HLock((Handle)*hWE);
- pWE = **hWE;
-
- // { get active port }
- GetPort(&pWE->port);
-
- // { determine whether temporary memory should be used for data structures }
- if (BTST(weFlags, weFUseTempMem))
- {
- allocFlags = allocFlags + kAllocTemp;
- }
-
- // { allocate the text handle (initially empty) }
- err = _WEAllocate(0, allocFlags, (Handle *)&pWE->hText);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { allocate the line array }
- err = _WEAllocate(2 * sizeof(LineRec), allocFlags, (Handle *)&pWE->hLines);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { allocate the style table }
- err = _WEAllocate(sizeof(StyleTableElement), allocFlags, (Handle *)&pWE->hStyles);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { allocate the run array }
- err = _WEAllocate(2 * sizeof(RunArrayElement), allocFlags, (Handle *)&pWE->hRuns);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { check for the presence of various system software features }
- // { determine whether Color QuickDraw is available }
- if (Gestalt(gestaltQuickdrawVersion, &response) == noErr)
- {
- if (response >= gestalt8BitQD)
- {
- BSET(weFlags, weFHasColorQD);
- }
- }
-
- // { determine whether the Text Services manager is available }
- if (Gestalt(gestaltTSMgrVersion, &response) == noErr)
- {
- BSET(weFlags, weFHasTextServices);
- }
-
- // { determine if there are any non-Roman scripts enabled }
- if (GetEnvirons(smEnabled) > 1)
- {
- BSET(weFlags, weFNonRoman);
- }
-
- // { determine whether a double-byte script is installed }
- if (GetEnvirons(smDoubleByte) != 0)
- {
- BSET(weFlags, weFDoubleByte);
- }
-
- // { initialize miscellaneous fields of the WE record }
- pWE->nLines = 1;
- pWE->nStyles = 1;
- pWE->nRuns = 1;
- pWE->viewRect = *viewRect;
- pWE->destRect = *destRect;
- pWE->flags = weFlags;
- pWE->tsmAreaStart = kInvalidOffset;
- pWE->tsmAreaEnd = kInvalidOffset;
-
- // { create a region to hold the view rectangle }
- pWE->viewRgn = NewRgn();
- WELongRectToRect(viewRect, &r);
- RectRgn(pWE->viewRgn, &r);
-
- // { initialize the style run array }
- (*pWE->hRuns)[1].runStart = 1;
- (*pWE->hRuns)[1].styleIndex = -1;
-
- // { initialize the style table }
- (*pWE->hStyles)[0].refCount = 1;
-
- // { copy text attributes from the active graphics port }
- (*pWE->hStyles)[0].info.runStyle.tsFont = pWE->port->txFont;
- (*pWE->hStyles)[0].info.runStyle.tsSize = pWE->port->txSize;
- (*pWE->hStyles)[0].info.runStyle.tsFace = ((GrafPtr1)pWE->port)->txFace;
- _WEFillFontInfo(pWE->port, &(*pWE->hStyles)[0].info);
- if (BTST(weFlags, weFHasColorQD))
- {
- GetForeColor(&(*pWE->hStyles)[0].info.runStyle.tsColor);
- }
-
- // { initialize the line array }
- err = WECalText(*hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { register with the Text Services Manager }
- err = _WERegisterWithTSM(*hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { unlock the WE record }
- HUnlock((Handle)*hWE);
-
- // { skip clean-up section }
- return noErr;
-
- cleanup:
- // { clean up }
- if (pWE != nil)
- {
- _WEForgetHandle((Handle *)&pWE->hText);
- _WEForgetHandle((Handle *)&pWE->hLines);
- _WEForgetHandle((Handle *)&pWE->hStyles);
- _WEForgetHandle((Handle *)&pWE->hRuns);
- if (pWE->viewRgn != nil)
- {
- DisposeRgn(pWE->viewRgn);
- }
- }
- _WEForgetHandle((Handle *)hWE);
-
- return err;
- }
-
- pascal void WEDispose(WEHandle hWE)
- {
- WEPtr pWE;
-
- // { sanity check: make sure WE isn't NIL }
- if (hWE == nil)
- {
- return;
- }
-
- // { lock the WE record }
- HLock((Handle)hWE);
- pWE = *hWE;
-
- // { dispose of auxiliary data structures }
- _WEForgetHandle((Handle *)&pWE->hText);
- _WEForgetHandle((Handle *)&pWE->hLines);
- _WEForgetHandle((Handle *)&pWE->hStyles);
- _WEForgetHandle((Handle *)&pWE->hRuns);
- DisposeRgn(pWE->viewRgn);
-
- // { dispose of the offscreen graphics world }
- if (pWE->offscreenPort != nil)
- {
- DisposeGWorld((GWorldPtr)pWE->offscreenPort);
- }
-
- // { unregister with the Text Services Manager }
- if (pWE->tsmReference != nil)
- {
- DeleteTSMDocument(pWE->tsmReference);
- }
-
- // { dispose of the WE record }
- DisposeHandle((Handle)hWE);
- }
-
- OSErr _WERemoveLine(long lineIndex, WEPtr pWE)
- {
- OSErr retval;
-
- // { remove the specified element from the line array }
-
- // { do the removal (errors returned by _WERemoveSlot can be safely ignored) }
- retval = _WERemoveSlot((Handle)pWE->hLines, lineIndex, sizeof(LineRec));
-
- // { decrement line count }
- pWE->nLines = pWE->nLines - 1;
-
- return retval;
- }
-
- OSErr InsertLine(long lineIndex, LineRec *theLine, WEPtr pWE)
- {
- // { insert the specified element in the line array }
-
- OSErr err;
-
- // { do the insertion }
- err = _WEInsertSlot((Handle)pWE->hLines, (Ptr)theLine, lineIndex, sizeof(LineRec));
- if (err != noErr)
- {
- return err;
- }
-
- // { increment line count }
- pWE->nLines = pWE->nLines + 1;
-
- return noErr;
- }
-
- void _WEBumpOrigin(long lineIndex, long deltaOrigin, WEPtr pWE)
- {
- long *pOrigin;
- long nLines;
-
- pOrigin = &((*pWE->hLines)[lineIndex].lineOrigin);
-
- // { loop through the line run array adjusting the lineOrigin fields }
- nLines = pWE->nLines;
- while (lineIndex <= nLines)
- {
- *pOrigin = *pOrigin + deltaOrigin;
- pOrigin = (long *)((long)pOrigin + sizeof(LineRec));
- lineIndex = lineIndex + 1;
- }
- }
-
- long _WEFindLineBreak(long lineStart, WEHandle hWE)
- {
- // { Find where to break the line beginning at lineStart }
- // { the WE record and the text must be already locked }
- // { the current graphics port must be already set up correctly }
-
- WEPtr pWE;
- Ptr pText;
- long offset, breakOffset;
- long textLength;
- long remainingLength;
- long segmentStart, segmentEnd;
- long runIndex;
- WERunInfo runInfo;
- Fixed pixelWidth;
- ScriptCode script, previousScript;
-
- pWE = *hWE;
- offset = lineStart;
- pText = *pWE->hText + offset;
- remainingLength = pWE->textLength - offset;
-
- // { find the style run index corresponding to the first segment on this line }
- runIndex = _WEOffsetToRun(offset, hWE);
-
- // { initialize pixelWidth to the width of the destination rectangle, as a Fixed quantity }
- pixelWidth = BSL(pWE->destRect.right - pWE->destRect.left, 16);
-
- // { STYLE SEGMENT LOOP }
- do
- {
-
- // { get style run information for the current style run }
- _WEGetIndStyle(runIndex, &runInfo, hWE);
- runIndex = runIndex + 1;
-
- // { set text attributes in the graphics port }
- TextFont(runInfo.runAttrs.runStyle.tsFont);
- TextFace(runInfo.runAttrs.runStyle.tsFace);
- TextSize(runInfo.runAttrs.runStyle.tsSize);
-
- // { if we're handling multiscript text, keep track of script boundaries }
- if (BTST(pWE->flags, weFNonRoman))
- {
- // { what is the script for this segment? }
- script = Font2Script(runInfo.runAttrs.runStyle.tsFont);
-
- // { have we crossed a script run boundary in the middle of a line? }
- if ((runInfo.runStart > offset) && (script != previousScript))
- {
- // { leave behind the all previous segments on this line }
- offset = runInfo.runStart;
- pText = *pWE->hText + offset;
- remainingLength = pWE->textLength - offset;
- }
- previousScript = script;
- } // { if non-Roman }
-
- // { we'll pass textLength as the second parameter to StyledLineBreak }
- // { although this parameter is declared as a long, StyledLineBreak uses only }
- // { the low word, so make sure it doesn't trespass the 32,767 byte threshold! }
- textLength = _WEPinInRange(remainingLength, 0, SHRT_MAX);
-
- // { calculate segmentStart and segmentEnd relative to offset }
- segmentStart = _WEPinInRange(runInfo.runStart - offset, 0, textLength);
- segmentEnd = _WEPinInRange(runInfo.runEnd - offset, 0, textLength);
-
- // { set breakOffset to a non-zero value for the first script run on the line, }
- // { set it to zero for all subsequent script runs }
- breakOffset = (offset == lineStart);
-
- // { keep looping until StyledLineBreak detects a break or we reach the end of the text }
- } while ((StyledLineBreak(pText, textLength, segmentStart, segmentEnd, 0, &pixelWidth, &breakOffset)
- == smBreakOverflow) && (segmentEnd < remainingLength));
-
- // { return the offset from lineStart to the break point }
- return (offset - lineStart) + breakOffset;
- }
-
- void _WECalcHeights(long rangeStart, long rangeEnd, short *lineAscent, short *lineDescent,
- WEHandle hWE)
- {
- // { Find the maximum ascent and descent values between rangeStart and rangeEnd }
- // { the WE record must be already locked }
- // { the current graphics port must be already set up correctly }
-
- long runIndex;
- WERunInfo runInfo;
- short runAscent, runDescent;
-
- *lineAscent = 1;
- *lineDescent = 1;
-
- // { find the style run index corresponding to the first segment on this line }
- runIndex = _WEOffsetToRun(rangeStart, hWE);
-
- // { STYLE SEGMENT LOOP }
- do
- {
- // { get style run information for the current style run }
- _WEGetIndStyle(runIndex, &runInfo, hWE);
- runIndex = runIndex + 1;
-
- // { calculate ascent and descent (actually, descent + leading) values for this style run }
- runAscent = runInfo.runAttrs.runAscent;
- runDescent = runInfo.runAttrs.runHeight - runAscent;
-
- // { save the maximum values in lineAscent and lineDescent }
- if (runAscent > *lineAscent)
- {
- *lineAscent = runAscent;
- }
- if (runDescent > *lineDescent)
- {
- *lineDescent = runDescent;
- }
-
- // { keep looping until we reach rangeEnd }
- } while (runInfo.runEnd < rangeEnd);
- }
-
- OSErr _WERecalBreaks(long *startLine, long *endLine, WEHandle hWE)
- {
- // { Recalculates line breaks, line heights and ascents for all the text or for a portion of it. }
- // { On entry, startLine and endLine define a range of lines to recalculate. }
- // { On exit, startLine to endLine defines the range of lines actually recalculated }
- // { the WE record must already be locked }
-
- WEPtr pWE;
- LinePtr pLine;
- LineRec lineInfo, oldLineInfo;
- long lineIndex;
- long recalThreshold;
- long lineOffset;
- short lineAscent, lineDescent;
- Boolean saveTextLock;
- QDEnvironment saveEnvironment;
- OSErr err;
- OSErr retval;
-
- retval = noErr;
- pWE = *hWE;
-
- // { lock the text }
- saveTextLock = _WESetHandleLock(pWE->hText, true);
-
- // { find the character offset that must be necessarily reached before we can }
- // { even consider the possibility of stopping the recalculation process }
- // { this offset, recalThreshold, is the last character on endLine _before_ recalculation }
- lineIndex = _WEPinInRange(*endLine, 0, pWE->nLines - 1);
- recalThreshold = (*pWE->hLines)[lineIndex + 1].lineStart;
-
- // { we start recalculating line breaks from the line actually _preceding_ startLine, }
- // { since editing startLine may cause part of its text to fit on the preceding line }
- lineIndex = _WEPinInRange(*startLine - 1, 0, pWE->nLines - 1);
-
- // { find where in the text recalculation should begin }
- lineInfo = (*pWE->hLines)[lineIndex];
-
- // { save the QuickDraw environment }
- _WESaveQDEnvironment(pWE->port, false, &saveEnvironment);
-
- // { MAIN LINE BREAKING LOOP }
- do
- {
- // { find where to break the current line }
- lineOffset = _WEFindLineBreak(lineInfo.lineStart, hWE);
-
- // { calculate ascent and descent values for this line }
- _WECalcHeights(lineInfo.lineStart, lineInfo.lineStart + lineOffset, &lineAscent, &lineDescent, hWE);
-
- // { save the maximum line ascent for this line in the line array }
- pLine = &(*pWE->hLines)[lineIndex];
- pLine->lineAscent = lineAscent;
-
- // { increment counters (go to the next line array entry) }
- lineIndex = lineIndex + 1;
- lineInfo.lineStart = lineInfo.lineStart + lineOffset;
- lineInfo.lineOrigin = lineInfo.lineOrigin + (lineAscent + lineDescent);
- pLine++;
-
- // { compare the newly calculated line start with the old value }
- // { if the new line start comes before the old line start, insert a new element }
- oldLineInfo = *pLine;
- if ((lineIndex > pWE->nLines) || (lineInfo.lineStart < oldLineInfo.lineStart))
- {
- err = InsertLine(lineIndex, &lineInfo, pWE);
-
- // { clean up and exit if we ran out of memory }
- if (err != noErr)
- {
- retval = err;
- goto cleanup;
- }
- }
- else
- {
- // { overwrite the old element }
- pLine->lineStart = lineInfo.lineStart;
- pLine->lineOrigin = lineInfo.lineOrigin;
-
- // { remove all further elements which have a lineStart field }
- // { less than or equal to the current one }
- while((lineIndex + 1 <= pWE->nLines) &&
- (lineInfo.lineStart >= (*pWE->hLines)[lineIndex + 1].lineStart))
- {
- err = _WERemoveLine(lineIndex + 1, pWE);
- }
-
- // { if the new line start is the same as the old one... }
- if (lineInfo.lineStart == oldLineInfo.lineStart)
- {
- // { ...and recalThreshold has been reached, we can stop recalculating line breaks }
- if (lineInfo.lineStart >= recalThreshold)
- {
- // { although line breaks need not be changed from lineIndex on, }
- // { the lineOrigin fields may need to be changed }
- if (lineInfo.lineOrigin != oldLineInfo.lineOrigin)
- {
- _WEBumpOrigin(lineIndex + 1, lineInfo.lineOrigin - oldLineInfo.lineOrigin, pWE);
- }
-
- // { exit from the line breaking loop }
- goto cleanup;
- }
- }
- else
- {
- // { otherwise, the new line start comes after the old line start... }
- // { if the current line is the one preceding startLine, warn our caller about this }
- if ((lineIndex > 0) && (lineIndex == *startLine))
- {
- *startLine = lineIndex - 1;
- }
- }
- }
- } while(lineInfo.lineStart < pWE->textLength);
-
- cleanup:
- // { set destRect.bottom to destRect.top + total text height }
- pWE->destRect.bottom = pWE->destRect.top + WEGetHeight(0, pWE->nLines, hWE);
-
- // { quirk: if the last character in the text is a carriage return, the caret appears }
- // { below the last line, so in this case we need to add the extra height to destRect.bottom }
- if (WEGetChar(pWE->textLength - 1, hWE) == '\r')
- {
- pWE->destRect.bottom = pWE->destRect.bottom +
- WEGetHeight(pWE->nLines - 1, pWE->nLines, hWE);
- }
-
- // { return through endLine the index of the last line affected by recalculation }
- *endLine = lineIndex - 1;
-
- // { make sure startLine isn't greater than endLine }
- if (*startLine > *endLine)
- {
- *startLine = *endLine;
- }
-
- // { unlock the text }
- _WESetHandleLock(pWE->hText, saveTextLock);
-
- // { restore the QuickDraw environment }
- _WERestoreQDEnvironment(&saveEnvironment);
- return retval;
- }
-
- Boolean SLCalcSlop(LinePtr pLine, WERunAttributesPtr pAttrs, Ptr pSegment, long segmentStart,
- long segmentLength, JustStyleCode styleRunPosition, void *callbackData);
-
-
- Boolean SLCalcSlop(LinePtr pLine, WERunAttributesPtr pAttrs, Ptr pSegment, long segmentStart,
- long segmentLength, JustStyleCode styleRunPosition, void *callbackData)
- {
- Boolean isEndOfLine;
- Boolean retval;
- struct SLCalcSlopData *p = (struct SLCalcSlopData *) callbackData;
-
- retval = false; // { keep looping }
-
- // { see if this text segment ends with a carriage return, or if we've reached the }
- // { end of the text (in which case we don't want any justification to take place) }
- isEndOfLine = (segmentStart + segmentLength >= p->pWE->textLength) ||
- ( *((Ptr)pSegment + segmentLength - 1) == kEOL);
-
- // { if this is the first segment on the line, reset line totals }
- if (styleRunPosition <= smLeftStyleRun)
- {
- p->totalSlop = p->lineWidth;
- p->totalProportion = 0;
- }
-
- // { if this is the last segment on the line, strip trailing spaces }
- if (!(styleRunPosition & 1))
- {
- segmentLength = VisibleLength(pSegment, segmentLength);
- }
-
- // { measure this segment and subtract its width from totalSlop }
- p->totalSlop = p->totalSlop - TextWidth(pSegment, 0, segmentLength);
-
- // { calculate the proportion of extra space to apply to this text segment }
- p->totalProportion = p->totalProportion + NPortionText(pSegment, segmentLength,
- styleRunPosition, *(Point *)&kOneToOneScaling, *(Point *)&kOneToOneScaling);
-
- // { if this is the last segment on the line, save values in the line array }
- if (!(styleRunPosition & 1))
- {
- pLine->lineSlop = p->totalSlop;
- if (isEndOfLine)
- {
- pLine->lineJustAmount = 0;
- }
- else
- {
- pLine->lineJustAmount = FixDiv(BSL(p->totalSlop, 16), p->totalProportion);
- }
- }
- return retval;
- }
-
-
- void _WERecalSlops(long firstLine, long lastLine, WEHandle hWE)
- {
- // { Calculates the lineSlop and lineJustAmount fields }
- // { of the line array for the specified lines }
-
- WEPtr pWE;
- short lineWidth;
- struct SLCalcSlopData callbackData;
-
- pWE = *hWE;
- lineWidth = pWE->destRect.right - pWE->destRect.left;
-
- // { calculate slop and normalized slop proportion for all lines }
- callbackData.lineWidth = lineWidth;
- callbackData.pWE = pWE;
- _WESegmentLoop(firstLine, lastLine, SLCalcSlop, (void *) &callbackData, hWE);
- }
-
- pascal OSErr WECalText(WEHandle hWE)
- {
- long startLine, endLine;
- Boolean saveWELock;
- OSErr err;
-
- // { lock WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
-
- // { recalculate all line breaks }
- startLine = 0;
- endLine = LONG_MAX;
- err = _WERecalBreaks(&startLine, &endLine, hWE);
-
- // { recalculate line slops }
- if (err == noErr)
- {
- _WERecalSlops(startLine, endLine, hWE);
- }
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
-
- // { return result code }
- return err;
- }
-
- pascal OSErr WEUseText(Handle text, WEHandle hWE)
- {
- WEPtr pWE;
- long textLength;
- Boolean saveWELock;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { install the text }
- _WEForgetHandle((Handle *)&pWE->hText);
- pWE->hText = text;
- textLength = GetHandleSize(text);
- pWE->textLength = textLength;
- (*pWE->hRuns)[pWE->nRuns].runStart = textLength + 1;
- (*pWE->hLines)[pWE->nLines].lineStart = textLength;
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
-
- return noErr;
- }
-
- pascal char WEGetAlignment(WEHandle hWE)
- {
- return (*hWE)->alignment;
- }
-
- pascal void WEGetSelection(long *selStart, long *selEnd, WEHandle hWE)
- {
- WEPtr pWE;
-
- pWE = *hWE;
- *selStart = pWE->selStart;
- *selEnd = pWE->selEnd;
- }
-
- pascal void WESetDestRect(LongRect *destRect, WEHandle hWE)
- {
- (*hWE)->destRect = *destRect;
- }
-
- pascal void WEGetDestRect(LongRect *destRect, WEHandle hWE)
- {
- *destRect = (*hWE)->destRect;
- }
-
- pascal void WESetViewRect(LongRect *viewRect, WEHandle hWE)
- {
- WEPtr pWE;
- Rect r;
-
- pWE = *hWE;
- pWE->viewRect = *viewRect;
-
- // { keep the viewRgn in sync with the view rectangle }
- WELongRectToRect(viewRect, &r);
- RectRgn(pWE->viewRgn, &r);
- }
-
- pascal void WEGetViewRect(LongRect *viewRect, WEHandle hWE)
- {
- *viewRect = (*hWE)->viewRect;
- }
-
- pascal long WEGetTextLength(WEHandle hWE)
- {
- return (*hWE)->textLength;
- }
-
- pascal long WECountLines(WEHandle hWE)
- {
- return (*hWE)->nLines;
- }
-
- pascal long WEGetHeight(long startLine, long endLine, WEHandle hWE)
- {
- WEPtr pWE;
- LineArrayPtr pLines;
- long nLines;
-
- pWE = *hWE;
- pLines = *pWE->hLines;
- nLines = pWE->nLines;
- startLine = _WEPinInRange(startLine, 0, nLines);
- endLine = _WEPinInRange(endLine, 0, nLines);
- _WEReorder(&startLine, &endLine);
- return pLines[endLine].lineOrigin - pLines[startLine].lineOrigin;
- }
-
- pascal Handle WEGetText(WEHandle hWE)
- {
- return (*hWE)->hText;
- }
-
- pascal char WEGetChar(long offset, WEHandle hWE)
- {
- WEPtr pWE;
-
- pWE = *hWE;
-
- // { sanity check: make sure offset is withing allowed bounds }
- if ((offset < 0) || (offset >= pWE->textLength))
- {
- return 0;
- }
-
- // { get the specified character (actually, byte) }
- return (*pWE->hText)[offset];
- }
-
- pascal short WECharByte(long offset, WEHandle hWE)
- {
- WEPtr pWE;
- WERunInfo info;
- short saveFont;
- GrafPtr savePort;
- short byte;
-
- pWE = *hWE;
-
- // { exit now if there is no double-byte script system installed }
- if (!BTST(pWE->flags, weFDoubleByte))
- {
- return smSingleByte;
- }
-
- // { sanity check: make sure offset is within allowed bounds }
- if ((offset < 0) || (offset >= pWE->textLength))
- {
- return smSingleByte;
- }
-
- // { get style information associated with the specified offset }
- WEGetRunInfo(offset, &info, hWE);
-
- // { save the port }
- GetPort(&savePort);
- SetPort(pWE->port);
-
- // { set the port font to the style run font }
- saveFont = pWE->port->txFont;
- TextFont(info.runAttrs.runStyle.tsFont);
-
- // { pass CharByte a pointer to the beginning of the style run }
- byte = CharByte((Ptr)(*pWE->hText) + info.runStart, offset - info.runStart);
-
- // { restore the port font }
- TextFont(saveFont);
-
- // { restore the port }
- SetPort(savePort);
-
- return byte;
- }
-
- pascal short WECharType(long offset, WEHandle hWE)
- {
- WEPtr pWE;
- WERunInfo info;
- Handle hText;
- short saveFont;
- GrafPtr savePort;
- Boolean saveTextLock;
- short retval;
-
- pWE = *hWE;
- hText = pWE->hText;
-
- // { sanity check: make sure offset is within allowed bounds }
- if ((offset < 0) || (offset >= pWE->textLength))
- {
- return 0;
- }
-
- // { get style information associated with the specified offset }
- WEGetRunInfo(offset, &info, hWE);
-
- // { save the port }
- GetPort(&savePort);
- SetPort(pWE->port);
-
- // { set the port font to the style run font }
- saveFont = pWE->port->txFont;
- TextFont(info.runAttrs.runStyle.tsFont);
-
- // { lock the text (CharType may move memory) }
- saveTextLock = _WESetHandleLock(hText, true);
-
- // { pass CharType a pointer to the beginning of the style run }
- retval = CharType((Ptr)*pWE->hText + info.runStart, offset - info.runStart);
-
- // { unlock the text }
- _WESetHandleLock(hText, saveTextLock);
-
- // { restore the port font }
- TextFont(saveFont);
-
- // { restore the port }
- SetPort(savePort);
-
- return retval;
- }
-
- pascal OSErr WECopyRange(long rangeStart, long rangeEnd, Handle hText, WEStyleScrapHandle
- hStyles, WEHandle hWE)
- {
-
- // { Make a copy of the specified range of text: store the characters in hText }
- // { and the associated style scrap in hStyles. The handles are resized as necessary. }
- // { Specify NIL in hText or hStyles if you don't want the corresponding info returned. }
-
- WEPtr pWE;
- long rangeLength;
- long firstRun, nRuns, i;
- long startChar;
- WERunInfo info;
- WEStyleScrapElementPtr pElement;
- Boolean saveWELock;
- OSErr err;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { range-check parameters and reorder them if necessary }
- rangeStart = _WEPinInRange(rangeStart, 0, pWE->textLength);
- rangeEnd = _WEPinInRange(rangeEnd, 0, pWE->textLength);
- _WEReorder(&rangeStart, &rangeEnd);
- rangeLength = rangeEnd - rangeStart;
-
- if (hText != nil)
- {
- // { resize the given handle }
- SetHandleSize(hText, rangeLength);
- err = MemError();
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { copy the text range }
- BlockMoveData((Ptr)*pWE->hText + rangeStart, (Ptr)*hText, rangeLength);
-
- }
-
- if (hStyles != nil)
- {
- // { count how many style runs there are in the selection range }
- firstRun = _WEOffsetToRun(rangeStart, hWE);
- nRuns = _WEOffsetToRun(rangeEnd - 1, hWE) - firstRun + 1;
-
- // { try to allocate a handle big enough to contain all these style runs }
- // { resize the given handle }
- SetHandleSize((Handle)hStyles, sizeof(short) + (nRuns * sizeof(ScrpSTElement)));
- err = MemError();
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { fill in the style count in the style scrap }
- // { *** POTENTIAL PROBLEM: if nRuns > 32767, scrpNStyles will be invalid *** }
- (*hStyles)->scrpNStyles = nRuns;
-
- // { fill the style scrap }
- pElement = &(*hStyles)->scrpStyleTab[0];
- for(i = 0; i<nRuns; i++)
- {
- _WEGetIndStyle(firstRun + i, &info, hWE);
- startChar = info.runStart - rangeStart;
- if (startChar < 0)
- {
- startChar = 0;
- }
- pElement->scrpStartChar = startChar;
- pElement->scrpAttrs = info.runAttrs;
- pElement->scrpAttrs.runStyle.tsFlags = 0;
- pElement++;
- }
- }
- // { clear result code }
- err = noErr;
-
- cleanup:
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- // { return result code }
- return err;
- }
-
- pascal OSErr WECopy(WEHandle hWE)
- {
- // { Copy the selection range to the desk scrap }
-
- WEPtr pWE;
- long selStart, selEnd;
- Handle hText, hStyles;
- OSErr err;
-
- pWE = *hWE;
- hText = nil;
- hStyles = nil;
-
- // { get selection range }
- selStart = pWE->selStart;
- selEnd = pWE->selEnd;
-
- // { do nothing if the selection range is empty }
- if (selStart < selEnd)
- {
- // { allocate two zero-length handles to hold a copy of the selection text and styles }
- err = _WEAllocate(0, kAllocTemp, (Handle *)&hText);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- err = _WEAllocate(0, kAllocTemp, (Handle *)&hStyles);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { make a copy of the selection text and styles }
- err = WECopyRange(selStart, selEnd, hText, (WEStyleScrapHandle)hStyles, hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { clear the desk scrap }
- err = ZeroScrap();
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { put the text }
- HLock(hText);
- err = PutScrap(GetHandleSize(hText), kTypeText, *hText);
- if (err != noErr)
- {
- goto cleanup;
- }
- HUnlock(hText);
-
- // { put the styles }
- HLock(hStyles);
- err = PutScrap(GetHandleSize(hStyles), kTypeStyles, *hStyles);
- if (err != noErr)
- {
- goto cleanup;
- }
- HUnlock(hStyles);
- }
- // { clear result code }
- err = noErr;
-
- cleanup:
- // { clean up }
- _WEForgetHandle((Handle *)&hText);
- _WEForgetHandle((Handle *)&hStyles);
-
- // { return result code }
- return err;
- }
-
- pascal short WEFeatureFlag(short feature, short action, WEHandle hWE)
- {
- WEPtr pWE;
- short retval;
-
- pWE = *hWE;
-
- // { return current status }
- retval = BTST(pWE->flags, feature) ? weBitSet : weBitClear;
-
- // { set new status if necessary }
- if (action == weBitClear)
- {
- BCLR(pWE->flags, feature);
- }
- else if (action == weBitSet)
- {
- BSET(pWE->flags, feature);
- }
-
- return retval;
- }
-
- pascal OSErr WEGetInfo(OSType selector, Ptr info, WEHandle hWE)
- {
- switch(selector)
- {
- case 'clik':
- *(long *)info = (long)(*hWE)->clickLoop;
- return noErr;
-
- case 'line':
- *(long *)info = (long)(*hWE)->hLines;
- return noErr;
-
- case 'port':
- *(long *)info = (long)(*hWE)->port;
- return noErr;
-
- case 'post':
- *(long *)info = (long)(*hWE)->tsmPostUpdate;
- return noErr;
-
- case 'pre ':
- *(long *)info = (long)(*hWE)->tsmPreUpdate;
- return noErr;
-
- case 'refc':
- *(long *)info = (*hWE)->refCon;
- return noErr;
-
- case 'runa':
- *(long *)info = (long)(*hWE)->hRuns;
- return noErr;
-
- case 'scrl':
- *(long *)info = (long)(*hWE)->scrollProc;
- return noErr;
-
- case 'styl':
- *(long *)info = (long)(*hWE)->hStyles;
- return noErr;
-
- case 'text':
- *(long *)info = (long)(*hWE)->hText;
- return noErr;
-
- case 'tsmd':
- *(long *)info = (long)(*hWE)->tsmReference;
- return noErr;
- }
- return paramErr;
- }
-
- pascal OSErr WESetInfo(OSType selector, Ptr info, WEHandle hWE)
- {
- switch(selector)
- {
- case 'clik':
- (*hWE)->clickLoop = (ProcPtr)*(long *)info;
- return noErr;
-
- case 'line':
- (*hWE)->hLines = (LineArrayHandle)*(long *)info;
- return noErr;
-
- case 'port':
- (*hWE)->port = (GrafPtr)*(long *)info;
- return noErr;
-
- case 'post':
- (*hWE)->tsmPostUpdate = (ProcPtr)*(long *)info;
- return noErr;
-
- case 'pre ':
- (*hWE)->tsmPreUpdate = (ProcPtr)*(long *)info;
- return noErr;
-
- case 'refc':
- (*hWE)->refCon = *(long *)info;
- return noErr;
-
- case 'runa':
- (*hWE)->hRuns = (RunArrayHandle)*(long *)info;
- return noErr;
-
- case 'scrl':
- (*hWE)->scrollProc = (ProcPtr)*(long *)info;
- return noErr;
-
- case 'styl':
- (*hWE)->hStyles = (StyleTableHandle)*(long *)info;
- return noErr;
-
- case 'text':
- (*hWE)->hText = (Handle)*(long *)info;
- return noErr;
-
- case 'tsmd':
- (*hWE)->tsmReference = (TSMDocumentID)*(long *)info;
- return noErr;
- }
-
- return paramErr;
- }
-