diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-07-22 15:34:08 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-07-22 15:34:08 +0300 |
commit | e0e53e4a51afcbd22345d12416645d3fc5483a18 (patch) | |
tree | 37c7ca552d60b6ccb179a807d9dbcfee8b097cfd /src/gmdocument.c | |
parent | e16f37f75399ef4dd2f267efbc720768489f96a1 (diff) |
Text wrapping; basic scrolling in DocumentWidget
Diffstat (limited to 'src/gmdocument.c')
-rw-r--r-- | src/gmdocument.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c index feff44e6..3f3f8358 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -150,11 +150,18 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
150 | run.text = (iRangecc){ bullet, bullet + strlen(bullet) }; | 150 | run.text = (iRangecc){ bullet, bullet + strlen(bullet) }; |
151 | pushBack_Array(&d->layout, &run); | 151 | pushBack_Array(&d->layout, &run); |
152 | } | 152 | } |
153 | run.text = line; | 153 | iRangecc runLine = line; |
154 | run.bounds.pos = addX_I2(pos, indent * gap_UI); | 154 | while (!isEmpty_Range(&runLine)) { |
155 | run.bounds.size = advanceRange_Text(run.font, line); | 155 | run.bounds.pos = addX_I2(pos, indent * gap_UI); |
156 | pushBack_Array(&d->layout, &run); | 156 | const char *contPos; |
157 | pos.y += run.bounds.size.y; | 157 | run.bounds.size = tryAdvanceRange_Text( |
158 | run.font, runLine, isPreformat ? 0 : (d->size.x - run.bounds.pos.x), &contPos); | ||
159 | run.text = (iRangecc){ runLine.start, contPos }; | ||
160 | pushBack_Array(&d->layout, &run); | ||
161 | runLine.start = contPos; | ||
162 | trimStart_Rangecc(&runLine); | ||
163 | pos.y += lineHeight_Text(run.font); | ||
164 | } | ||
158 | prevType = type; | 165 | prevType = type; |
159 | } | 166 | } |
160 | d->size.y = pos.y; | 167 | d->size.y = pos.y; |
@@ -185,9 +192,22 @@ static void normalize_GmDocument(iGmDocument *d) { | |||
185 | iRangecc src = range_String(&d->source); | 192 | iRangecc src = range_String(&d->source); |
186 | iRangecc line = iNullRange; | 193 | iRangecc line = iNullRange; |
187 | iBool isPreformat = iFalse; | 194 | iBool isPreformat = iFalse; |
195 | const int preTabWidth = 4; /* TODO: user-configurable parameter */ | ||
188 | while (nextSplit_Rangecc(&src, "\n", &line)) { | 196 | while (nextSplit_Rangecc(&src, "\n", &line)) { |
189 | if (isPreformat) { | 197 | if (isPreformat) { |
190 | appendRange_String(normalized, line); | 198 | /* Replace any tab characters with spaces for visualization. */ |
199 | for (const char *ch = line.start; ch != line.end; ch++) { | ||
200 | if (*ch == '\t') { | ||
201 | int column = ch - line.start; | ||
202 | int numSpaces = (column / preTabWidth + 1) * preTabWidth - column; | ||
203 | while (numSpaces-- > 0) { | ||
204 | appendCStrN_String(normalized, " ", 1); | ||
205 | } | ||
206 | } | ||
207 | else { | ||
208 | appendCStrN_String(normalized, ch, 1); | ||
209 | } | ||
210 | } | ||
191 | appendCStr_String(normalized, "\n"); | 211 | appendCStr_String(normalized, "\n"); |
192 | if (lineType_Rangecc_(&line) == preformatted_GmLineType) { | 212 | if (lineType_Rangecc_(&line) == preformatted_GmLineType) { |
193 | isPreformat = iFalse; | 213 | isPreformat = iFalse; |
@@ -202,21 +222,23 @@ static void normalize_GmDocument(iGmDocument *d) { | |||
202 | } | 222 | } |
203 | iBool isPrevSpace = iFalse; | 223 | iBool isPrevSpace = iFalse; |
204 | for (const char *ch = line.start; ch != line.end; ch++) { | 224 | for (const char *ch = line.start; ch != line.end; ch++) { |
205 | if (isNormalizableSpace_(*ch)) { | 225 | char c = *ch; |
226 | if (isNormalizableSpace_(c)) { | ||
206 | if (isPrevSpace) { | 227 | if (isPrevSpace) { |
207 | continue; | 228 | continue; /* skip repeated spaces */ |
208 | } | 229 | } |
230 | c = ' '; | ||
209 | isPrevSpace = iTrue; | 231 | isPrevSpace = iTrue; |
210 | } | 232 | } |
211 | else { | 233 | else { |
212 | isPrevSpace = iFalse; | 234 | isPrevSpace = iFalse; |
213 | } | 235 | } |
214 | appendCStrN_String(normalized, ch, 1); | 236 | appendCStrN_String(normalized, &c, 1); |
215 | } | 237 | } |
216 | appendCStr_String(normalized, "\n"); | 238 | appendCStr_String(normalized, "\n"); |
217 | } | 239 | } |
218 | set_String(&d->source, collect_String(normalized)); | 240 | set_String(&d->source, collect_String(normalized)); |
219 | printf("normalized:\n%s\n", cstr_String(&d->source)); | 241 | // printf("normalized:\n%s\n", cstr_String(&d->source)); |
220 | } | 242 | } |
221 | 243 | ||
222 | void setSource_GmDocument(iGmDocument *d, const iString *source, int width) { | 244 | void setSource_GmDocument(iGmDocument *d, const iString *source, int width) { |
@@ -244,4 +266,8 @@ void render_GmDocument(const iGmDocument *d, iRangei visRangeY, iGmDocumentRende | |||
244 | } | 266 | } |
245 | } | 267 | } |
246 | 268 | ||
269 | iInt2 size_GmDocument(const iGmDocument *d) { | ||
270 | return d->size; | ||
271 | } | ||
272 | |||
247 | iDefineClass(GmDocument) | 273 | iDefineClass(GmDocument) |