282 lines
6.3 KiB
C
282 lines
6.3 KiB
C
/*
|
|
* WETabHooks.c
|
|
*
|
|
* WASTE TABS PACKAGE
|
|
* Hooks for adding tab support to WASTE
|
|
*
|
|
* Written by:
|
|
* Mark Alldritt (original code)
|
|
* Dan Crevier (line breaks)
|
|
* John Daub (maintenance)
|
|
* Jonathan Kew (variable-width tabs)
|
|
* Marco Piovanelli (?)
|
|
* Bert Seltzer (horizontal scrolling)
|
|
*
|
|
*/
|
|
|
|
#include "WETabs.h"
|
|
#include "WETabHooks.h"
|
|
|
|
#define FIXROUND(f) ((SInt16) (((f) + 0x00008000) >> 16))
|
|
#define BSL(A, B) (((SInt32) (A)) << (B))
|
|
|
|
static const Point kOneToOneScaling = { 1, 1 } ;
|
|
|
|
pascal void _WETabDrawText
|
|
(
|
|
const char * pText,
|
|
SInt32 textLength,
|
|
Fixed slop,
|
|
JustStyleCode styleRunPosition,
|
|
WEReference we
|
|
)
|
|
{
|
|
#pragma unused ( slop, styleRunPosition )
|
|
|
|
LongRect destRect;
|
|
SInt32 beginChar = 0;
|
|
SInt32 ii;
|
|
SInt16 tabWidth;
|
|
SInt16 destLeft;
|
|
Point penPos;
|
|
SInt16 tabSize = WEGetTabSize(we);
|
|
|
|
WEGetDestRect(&destRect, we);
|
|
destLeft = (SInt16) destRect.left;
|
|
|
|
for ( ii = 0; ii < textLength; ii++ )
|
|
{
|
|
if (pText[ii] == '\t')
|
|
{
|
|
DrawText(pText, beginChar, ii - beginChar);
|
|
|
|
/* advance the pen to the next tab stop */
|
|
GetPen(&penPos);
|
|
tabWidth = tabSize - (penPos.h - destLeft) % tabSize;
|
|
MoveTo(penPos.h + tabWidth, penPos.v);
|
|
beginChar = ii + 1;
|
|
}
|
|
} /* for */
|
|
|
|
DrawText(pText, beginChar, textLength - beginChar);
|
|
}
|
|
|
|
pascal SInt32 _WETabPixelToChar
|
|
(
|
|
const char * pText,
|
|
SInt32 textLength,
|
|
Fixed slop,
|
|
Fixed *width,
|
|
WEEdge *edge,
|
|
JustStyleCode styleRunPosition,
|
|
Fixed hPos,
|
|
WEReference we
|
|
)
|
|
{
|
|
SInt32 beginChar = 0;
|
|
SInt32 offset = 0;
|
|
SInt32 ii;
|
|
Fixed lastWidth;
|
|
Fixed tabWidth;
|
|
SInt16 tabSize = WEGetTabSize(we);
|
|
|
|
/* loop through every character in the segment looking for tabs */
|
|
for ( ii = 0; ii < textLength; ii++ )
|
|
{
|
|
/* exit now if width has gone negative */
|
|
/* (i.e., if we have found which glyph was hit) */
|
|
if (*width <= 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
/* tab found? */
|
|
if (pText[ii] == '\t')
|
|
{
|
|
/* calculate the width of the sub-segment preceding the tab */
|
|
lastWidth = *width;
|
|
offset += PixelToChar((char *)pText + beginChar, ii - beginChar, slop,
|
|
lastWidth, (Boolean *) edge, width, styleRunPosition,
|
|
kOneToOneScaling, kOneToOneScaling);
|
|
beginChar = ii + 1;
|
|
|
|
/* hit point past sub-segment? */
|
|
if (*width >= 0)
|
|
{
|
|
/* increment hPos by width of sub-segment preceding the tab */
|
|
hPos += (lastWidth - *width);
|
|
|
|
/* calculate the width of the tab "glyph" (as a Fixed value) */
|
|
tabWidth = BSL(tabSize - FIXROUND(hPos) % tabSize, 16);
|
|
|
|
/* increment hPos by width of tab character */
|
|
hPos += tabWidth;
|
|
|
|
/* hit point within tab glyph? */
|
|
if (*width < tabWidth)
|
|
{
|
|
/* yes: determine which half of tab glyph was hit */
|
|
if (*width > (tabWidth >> 1))
|
|
{
|
|
*edge = kTrailingEdge; /* second (trailing) edge of tab */
|
|
offset++;
|
|
}
|
|
else
|
|
{
|
|
*edge = kLeadingEdge; /* first (leading) edge of tab */
|
|
}
|
|
|
|
/* returning -1 (as Fixed) in width means we're finished */
|
|
*width = 0xFFFF0000;
|
|
}
|
|
else
|
|
{
|
|
/* hit point is past tab: keep looping */
|
|
offset++;
|
|
*width -= tabWidth;
|
|
}
|
|
} /* if (*width >= 0) */
|
|
} /* if tab found */
|
|
} /* for */
|
|
|
|
/* no more tabs in this segment: process the last sub-segment */
|
|
if (*width >= 0)
|
|
{
|
|
lastWidth = *width;
|
|
offset += PixelToChar((char *)pText + beginChar, textLength - beginChar, slop,
|
|
lastWidth, (Boolean *) edge, width, styleRunPosition,
|
|
kOneToOneScaling, kOneToOneScaling);
|
|
}
|
|
|
|
/* round width to nearest integer value */
|
|
/* this is supposed to fix an incompatibility with the WorldScript Power Adapter */
|
|
*width = (*width + 0x00008000) & 0xFFFF0000;
|
|
|
|
return offset;
|
|
}
|
|
|
|
pascal SInt16 _WETabCharToPixel
|
|
(
|
|
const char * pText,
|
|
SInt32 textLength,
|
|
Fixed slop,
|
|
SInt32 offset,
|
|
SInt16 direction,
|
|
JustStyleCode styleRunPosition,
|
|
SInt16 hPos,
|
|
WEReference we
|
|
)
|
|
{
|
|
LongRect destRect;
|
|
SInt32 beginChar = 0;
|
|
SInt32 ii;
|
|
SInt16 width;
|
|
SInt16 destLeft;
|
|
SInt16 totalWidth = 0;
|
|
SInt16 tabSize = WEGetTabSize(we);
|
|
|
|
WEGetDestRect(&destRect, we);
|
|
destLeft = (SInt16) destRect.left;
|
|
|
|
/* measure text up to offset, if offset is within this segment,
|
|
otherwise to textLength */
|
|
if (offset > textLength)
|
|
{
|
|
offset = textLength;
|
|
}
|
|
|
|
for ( ii = 0; ii < offset; ii++ )
|
|
{
|
|
if (pText[ii] == '\t')
|
|
{
|
|
/* calculate the pixel width of the subsegment preceding the tab */
|
|
width = TextWidth(pText, beginChar, ii - beginChar);
|
|
totalWidth += width;
|
|
hPos += width;
|
|
|
|
/* calculate tab width */
|
|
width = tabSize - (hPos - destLeft) % tabSize;
|
|
totalWidth += width;
|
|
hPos += width;
|
|
|
|
/* go to next subsegment */
|
|
beginChar = ii + 1;
|
|
}
|
|
} /* for */
|
|
|
|
/* calculate width of remaining characters */
|
|
width = CharToPixel((char *)pText + beginChar, textLength - beginChar, slop,
|
|
offset - beginChar, direction, styleRunPosition,
|
|
kOneToOneScaling, kOneToOneScaling);
|
|
totalWidth += width;
|
|
|
|
return totalWidth;
|
|
}
|
|
|
|
pascal StyledLineBreakCode _WETabLineBreak
|
|
(
|
|
const char * pText,
|
|
SInt32 textLength,
|
|
SInt32 textStart,
|
|
SInt32 textEnd,
|
|
Fixed *textWidth,
|
|
SInt32 *textOffset,
|
|
WEReference we
|
|
)
|
|
{
|
|
LongRect destRect;
|
|
SInt32 beginChar = textStart;
|
|
SInt32 ii;
|
|
Fixed tabWidth;
|
|
SInt16 destWidth;
|
|
StyledLineBreakCode breakCode = smBreakOverflow;
|
|
SInt16 tabSize = WEGetTabSize(we);
|
|
|
|
WEGetDestRect(&destRect, we);
|
|
destWidth = (SInt16) (destRect.right - destRect.left);
|
|
|
|
for ( ii = textStart; ii < textEnd; ii++ )
|
|
{
|
|
if (pText[ii] == 0x0D)
|
|
{
|
|
/* found a <return>, so stop looking ahead for tabs */
|
|
ii++;
|
|
break;
|
|
}
|
|
if (pText[ii] == '\t')
|
|
{
|
|
/* do previous "segment" */
|
|
breakCode = StyledLineBreak((char *)pText, textLength, beginChar, ii, 0, textWidth, textOffset);
|
|
if ((breakCode != smBreakOverflow) || (ii >= textLength))
|
|
{
|
|
break;
|
|
}
|
|
beginChar = ii + 1;
|
|
|
|
/* calculate tab width (as a Fixed value) */
|
|
tabWidth = BSL(tabSize - (destWidth - FIXROUND(*textWidth)) % tabSize, 16);
|
|
|
|
/* if tabWidth > pixelWidth we break in tab */
|
|
/* don't move tab to next line */
|
|
if (tabWidth > *textWidth)
|
|
{
|
|
breakCode = smBreakWord;
|
|
*textOffset = ii + 1;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
*textWidth -= tabWidth;
|
|
}
|
|
}
|
|
} /* for */
|
|
|
|
/* do last sub-segment */
|
|
if ((ii - beginChar >= 0) && (breakCode == smBreakOverflow))
|
|
{
|
|
breakCode = StyledLineBreak((char *)pText, textLength, beginChar, ii, 0, textWidth, textOffset);
|
|
}
|
|
|
|
return breakCode;
|
|
}
|