blob: 9595daf797925c6b48f92d14f20dfdbbd53dc4df [file] [log] [blame]
Jack Jansenc982ef22001-02-15 22:56:41 +00001/*
2 * WETabHooks.c
3 *
4 * WASTE TABS PACKAGE
5 * Hooks for adding tab support to WASTE
6 *
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)
14 *
15 */
16
17#include "WETabs.h"
18#include "WETabHooks.h"
19
20#define FIXROUND(f) ((SInt16) (((f) + 0x00008000) >> 16))
21#define BSL(A, B) (((SInt32) (A)) << (B))
22
23static const Point kOneToOneScaling = { 1, 1 } ;
24
25pascal void _WETabDrawText
26 (
27 const char * pText,
28 SInt32 textLength,
29 Fixed slop,
30 JustStyleCode styleRunPosition,
31 WEReference we
32 )
33{
34#pragma unused ( slop, styleRunPosition )
35
36 LongRect destRect;
37 SInt32 beginChar = 0;
38 SInt32 ii;
39 SInt16 tabWidth;
40 SInt16 destLeft;
41 Point penPos;
42 SInt16 tabSize = WEGetTabSize(we);
43
44 WEGetDestRect(&destRect, we);
45 destLeft = (SInt16) destRect.left;
46
47 for ( ii = 0; ii < textLength; ii++ )
48 {
49 if (pText[ii] == '\t')
50 {
51 DrawText(pText, beginChar, ii - beginChar);
52
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;
58 }
59 } /* for */
60
61 DrawText(pText, beginChar, textLength - beginChar);
62}
63
64pascal SInt32 _WETabPixelToChar
65 (
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
74 )
75{
76 SInt32 beginChar = 0;
77 SInt32 offset = 0;
78 SInt32 ii;
79 Fixed lastWidth;
80 Fixed tabWidth;
81 SInt16 tabSize = WEGetTabSize(we);
82
83 /* loop through every character in the segment looking for tabs */
84 for ( ii = 0; ii < textLength; ii++ )
85 {
86 /* exit now if width has gone negative */
87 /* (i.e., if we have found which glyph was hit) */
88 if (*width <= 0)
89 {
90 break;
91 }
92
93 /* tab found? */
94 if (pText[ii] == '\t')
95 {
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;
102
103 /* hit point past sub-segment? */
104 if (*width >= 0)
105 {
106 /* increment hPos by width of sub-segment preceding the tab */
107 hPos += (lastWidth - *width);
108
109 /* calculate the width of the tab "glyph" (as a Fixed value) */
110 tabWidth = BSL(tabSize - FIXROUND(hPos) % tabSize, 16);
111
112 /* increment hPos by width of tab character */
113 hPos += tabWidth;
114
115 /* hit point within tab glyph? */
116 if (*width < tabWidth)
117 {
118 /* yes: determine which half of tab glyph was hit */
119 if (*width > (tabWidth >> 1))
120 {
121 *edge = kTrailingEdge; /* second (trailing) edge of tab */
122 offset++;
123 }
124 else
125 {
126 *edge = kLeadingEdge; /* first (leading) edge of tab */
127 }
128
129 /* returning -1 (as Fixed) in width means we're finished */
130 *width = 0xFFFF0000;
131 }
132 else
133 {
134 /* hit point is past tab: keep looping */
135 offset++;
136 *width -= tabWidth;
137 }
138 } /* if (*width >= 0) */
139 } /* if tab found */
140 } /* for */
141
142 /* no more tabs in this segment: process the last sub-segment */
143 if (*width >= 0)
144 {
145 lastWidth = *width;
146 offset += PixelToChar((char *)pText + beginChar, textLength - beginChar, slop,
147 lastWidth, (Boolean *) edge, width, styleRunPosition,
148 kOneToOneScaling, kOneToOneScaling);
149 }
150
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;
154
155 return offset;
156}
157
158pascal SInt16 _WETabCharToPixel
159 (
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
168 )
169{
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);
177
178 WEGetDestRect(&destRect, we);
179 destLeft = (SInt16) destRect.left;
180
181 /* measure text up to offset, if offset is within this segment,
182 otherwise to textLength */
183 if (offset > textLength)
184 {
185 offset = textLength;
186 }
187
188 for ( ii = 0; ii < offset; ii++ )
189 {
190 if (pText[ii] == '\t')
191 {
192 /* calculate the pixel width of the subsegment preceding the tab */
193 width = TextWidth(pText, beginChar, ii - beginChar);
194 totalWidth += width;
195 hPos += width;
196
197 /* calculate tab width */
198 width = tabSize - (hPos - destLeft) % tabSize;
199 totalWidth += width;
200 hPos += width;
201
202 /* go to next subsegment */
203 beginChar = ii + 1;
204 }
205 } /* for */
206
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;
212
213 return totalWidth;
214}
215
216pascal StyledLineBreakCode _WETabLineBreak
217 (
218 const char * pText,
219 SInt32 textLength,
220 SInt32 textStart,
221 SInt32 textEnd,
222 Fixed *textWidth,
223 SInt32 *textOffset,
224 WEReference we
225 )
226{
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);
234
235 WEGetDestRect(&destRect, we);
236 destWidth = (SInt16) (destRect.right - destRect.left);
237
238 for ( ii = textStart; ii < textEnd; ii++ )
239 {
240 if (pText[ii] == 0x0D)
241 {
242 /* found a <return>, so stop looking ahead for tabs */
243 ii++;
244 break;
245 }
246 if (pText[ii] == '\t')
247 {
248 /* do previous "segment" */
249 breakCode = StyledLineBreak((char *)pText, textLength, beginChar, ii, 0, textWidth, textOffset);
250 if ((breakCode != smBreakOverflow) || (ii >= textLength))
251 {
252 break;
253 }
254 beginChar = ii + 1;
255
256 /* calculate tab width (as a Fixed value) */
257 tabWidth = BSL(tabSize - (destWidth - FIXROUND(*textWidth)) % tabSize, 16);
258
259 /* if tabWidth > pixelWidth we break in tab */
260 /* don't move tab to next line */
261 if (tabWidth > *textWidth)
262 {
263 breakCode = smBreakWord;
264 *textOffset = ii + 1;
265 break;
266 }
267 else
268 {
269 *textWidth -= tabWidth;
270 }
271 }
272 } /* for */
273
274 /* do last sub-segment */
275 if ((ii - beginChar >= 0) && (breakCode == smBreakOverflow))
276 {
277 breakCode = StyledLineBreak((char *)pText, textLength, beginChar, ii, 0, textWidth, textOffset);
278 }
279
280 return breakCode;
281}