py-cvs-rel2_1 (Rev 1.2) merge
[python/dscho.git] / Mac / Wastemods / WETabHooks.c
blob9595daf797925c6b48f92d14f20dfdbbd53dc4df
1 /*
2 * WETabHooks.c
4 * WASTE TABS PACKAGE
5 * Hooks for adding tab support to WASTE
7 * Written by:
8 * Mark Alldritt (original code)
9 * Dan Crevier (line breaks)
10 * John Daub (maintenance)
11 * Jonathan Kew (variable-width tabs)
12 * Marco Piovanelli (?)
13 * Bert Seltzer (horizontal scrolling)
17 #include "WETabs.h"
18 #include "WETabHooks.h"
20 #define FIXROUND(f) ((SInt16) (((f) + 0x00008000) >> 16))
21 #define BSL(A, B) (((SInt32) (A)) << (B))
23 static const Point kOneToOneScaling = { 1, 1 } ;
25 pascal void _WETabDrawText
27 const char * pText,
28 SInt32 textLength,
29 Fixed slop,
30 JustStyleCode styleRunPosition,
31 WEReference we
34 #pragma unused ( slop, styleRunPosition )
36 LongRect destRect;
37 SInt32 beginChar = 0;
38 SInt32 ii;
39 SInt16 tabWidth;
40 SInt16 destLeft;
41 Point penPos;
42 SInt16 tabSize = WEGetTabSize(we);
44 WEGetDestRect(&destRect, we);
45 destLeft = (SInt16) destRect.left;
47 for ( ii = 0; ii < textLength; ii++ )
49 if (pText[ii] == '\t')
51 DrawText(pText, beginChar, ii - beginChar);
53 /* advance the pen to the next tab stop */
54 GetPen(&penPos);
55 tabWidth = tabSize - (penPos.h - destLeft) % tabSize;
56 MoveTo(penPos.h + tabWidth, penPos.v);
57 beginChar = ii + 1;
59 } /* for */
61 DrawText(pText, beginChar, textLength - beginChar);
64 pascal SInt32 _WETabPixelToChar
66 const char * pText,
67 SInt32 textLength,
68 Fixed slop,
69 Fixed *width,
70 WEEdge *edge,
71 JustStyleCode styleRunPosition,
72 Fixed hPos,
73 WEReference we
76 SInt32 beginChar = 0;
77 SInt32 offset = 0;
78 SInt32 ii;
79 Fixed lastWidth;
80 Fixed tabWidth;
81 SInt16 tabSize = WEGetTabSize(we);
83 /* loop through every character in the segment looking for tabs */
84 for ( ii = 0; ii < textLength; ii++ )
86 /* exit now if width has gone negative */
87 /* (i.e., if we have found which glyph was hit) */
88 if (*width <= 0)
90 break;
93 /* tab found? */
94 if (pText[ii] == '\t')
96 /* calculate the width of the sub-segment preceding the tab */
97 lastWidth = *width;
98 offset += PixelToChar((char *)pText + beginChar, ii - beginChar, slop,
99 lastWidth, (Boolean *) edge, width, styleRunPosition,
100 kOneToOneScaling, kOneToOneScaling);
101 beginChar = ii + 1;
103 /* hit point past sub-segment? */
104 if (*width >= 0)
106 /* increment hPos by width of sub-segment preceding the tab */
107 hPos += (lastWidth - *width);
109 /* calculate the width of the tab "glyph" (as a Fixed value) */
110 tabWidth = BSL(tabSize - FIXROUND(hPos) % tabSize, 16);
112 /* increment hPos by width of tab character */
113 hPos += tabWidth;
115 /* hit point within tab glyph? */
116 if (*width < tabWidth)
118 /* yes: determine which half of tab glyph was hit */
119 if (*width > (tabWidth >> 1))
121 *edge = kTrailingEdge; /* second (trailing) edge of tab */
122 offset++;
124 else
126 *edge = kLeadingEdge; /* first (leading) edge of tab */
129 /* returning -1 (as Fixed) in width means we're finished */
130 *width = 0xFFFF0000;
132 else
134 /* hit point is past tab: keep looping */
135 offset++;
136 *width -= tabWidth;
138 } /* if (*width >= 0) */
139 } /* if tab found */
140 } /* for */
142 /* no more tabs in this segment: process the last sub-segment */
143 if (*width >= 0)
145 lastWidth = *width;
146 offset += PixelToChar((char *)pText + beginChar, textLength - beginChar, slop,
147 lastWidth, (Boolean *) edge, width, styleRunPosition,
148 kOneToOneScaling, kOneToOneScaling);
151 /* round width to nearest integer value */
152 /* this is supposed to fix an incompatibility with the WorldScript Power Adapter */
153 *width = (*width + 0x00008000) & 0xFFFF0000;
155 return offset;
158 pascal SInt16 _WETabCharToPixel
160 const char * pText,
161 SInt32 textLength,
162 Fixed slop,
163 SInt32 offset,
164 SInt16 direction,
165 JustStyleCode styleRunPosition,
166 SInt16 hPos,
167 WEReference we
170 LongRect destRect;
171 SInt32 beginChar = 0;
172 SInt32 ii;
173 SInt16 width;
174 SInt16 destLeft;
175 SInt16 totalWidth = 0;
176 SInt16 tabSize = WEGetTabSize(we);
178 WEGetDestRect(&destRect, we);
179 destLeft = (SInt16) destRect.left;
181 /* measure text up to offset, if offset is within this segment,
182 otherwise to textLength */
183 if (offset > textLength)
185 offset = textLength;
188 for ( ii = 0; ii < offset; ii++ )
190 if (pText[ii] == '\t')
192 /* calculate the pixel width of the subsegment preceding the tab */
193 width = TextWidth(pText, beginChar, ii - beginChar);
194 totalWidth += width;
195 hPos += width;
197 /* calculate tab width */
198 width = tabSize - (hPos - destLeft) % tabSize;
199 totalWidth += width;
200 hPos += width;
202 /* go to next subsegment */
203 beginChar = ii + 1;
205 } /* for */
207 /* calculate width of remaining characters */
208 width = CharToPixel((char *)pText + beginChar, textLength - beginChar, slop,
209 offset - beginChar, direction, styleRunPosition,
210 kOneToOneScaling, kOneToOneScaling);
211 totalWidth += width;
213 return totalWidth;
216 pascal StyledLineBreakCode _WETabLineBreak
218 const char * pText,
219 SInt32 textLength,
220 SInt32 textStart,
221 SInt32 textEnd,
222 Fixed *textWidth,
223 SInt32 *textOffset,
224 WEReference we
227 LongRect destRect;
228 SInt32 beginChar = textStart;
229 SInt32 ii;
230 Fixed tabWidth;
231 SInt16 destWidth;
232 StyledLineBreakCode breakCode = smBreakOverflow;
233 SInt16 tabSize = WEGetTabSize(we);
235 WEGetDestRect(&destRect, we);
236 destWidth = (SInt16) (destRect.right - destRect.left);
238 for ( ii = textStart; ii < textEnd; ii++ )
240 if (pText[ii] == 0x0D)
242 /* found a <return>, so stop looking ahead for tabs */
243 ii++;
244 break;
246 if (pText[ii] == '\t')
248 /* do previous "segment" */
249 breakCode = StyledLineBreak((char *)pText, textLength, beginChar, ii, 0, textWidth, textOffset);
250 if ((breakCode != smBreakOverflow) || (ii >= textLength))
252 break;
254 beginChar = ii + 1;
256 /* calculate tab width (as a Fixed value) */
257 tabWidth = BSL(tabSize - (destWidth - FIXROUND(*textWidth)) % tabSize, 16);
259 /* if tabWidth > pixelWidth we break in tab */
260 /* don't move tab to next line */
261 if (tabWidth > *textWidth)
263 breakCode = smBreakWord;
264 *textOffset = ii + 1;
265 break;
267 else
269 *textWidth -= tabWidth;
272 } /* for */
274 /* do last sub-segment */
275 if ((ii - beginChar >= 0) && (breakCode == smBreakOverflow))
277 breakCode = StyledLineBreak((char *)pText, textLength, beginChar, ii, 0, textWidth, textOffset);
280 return breakCode;