Changeset View
Changeset View
Standalone View
Standalone View
src/buffer/katetextblock.cpp
Show First 20 Lines • Show All 144 Lines • ▼ Show 20 Line(s) | 92 | { | |||
---|---|---|---|---|---|
145 | 145 | | |||
146 | // no cursors in this block, no work to do.. | 146 | // no cursors in this block, no work to do.. | ||
147 | if (m_cursors.empty()) { | 147 | if (m_cursors.empty()) { | ||
148 | return; | 148 | return; | ||
149 | } | 149 | } | ||
150 | 150 | | |||
151 | // move all cursors on the line which has the text inserted | 151 | // move all cursors on the line which has the text inserted | ||
152 | // remember all ranges modified | 152 | // remember all ranges modified | ||
153 | QSet<TextRange *> changedRanges; | 153 | std::vector<TextRange *> changedRanges; | ||
anthonyfieroni: You can use unordered_set, so you don't need m_isCheckValidityRequired any more. It can be… | |||||
Actually no, that will be again a lot more expensive. cullmann: Actually no, that will be again a lot more expensive.
With the vector, you get one allocation… | |||||
154 | foreach (TextCursor *cursor, m_cursors) { | 154 | foreach (TextCursor *cursor, m_cursors) { | ||
155 | // skip cursors on lines in front of the wrapped one! | 155 | // skip cursors on lines in front of the wrapped one! | ||
156 | if (cursor->lineInBlock() < line) { | 156 | if (cursor->lineInBlock() < line) { | ||
157 | continue; | 157 | continue; | ||
158 | } | 158 | } | ||
159 | 159 | | |||
160 | // either this is simple, line behind the wrapped one | 160 | // either this is simple, line behind the wrapped one | ||
161 | if (cursor->lineInBlock() > line) { | 161 | if (cursor->lineInBlock() > line) { | ||
Show All 16 Lines | 167 | else { | |||
178 | cursor->m_line++; | 178 | cursor->m_line++; | ||
179 | 179 | | |||
180 | // patch column | 180 | // patch column | ||
181 | cursor->m_column -= position.column(); | 181 | cursor->m_column -= position.column(); | ||
182 | } | 182 | } | ||
183 | 183 | | |||
184 | // remember range, if any | 184 | // remember range, if any | ||
185 | if (cursor->kateRange()) { | 185 | if (cursor->kateRange()) { | ||
186 | changedRanges.insert(cursor->kateRange()); | 186 | cursor->kateRange()->setValidityCheckRequired(); | ||
187 | changedRanges.push_back(cursor->kateRange()); | ||||
187 | } | 188 | } | ||
188 | } | 189 | } | ||
189 | 190 | | |||
190 | // check validity of all ranges, might invalidate them... | 191 | // we might need to invalidate ranges or notify about their changes | ||
191 | foreach (TextRange *range, changedRanges) { | 192 | for (TextRange *range : changedRanges) { | ||
193 | if (range->isValidityCheckRequired()) { | ||||
192 | range->checkValidity(); | 194 | range->checkValidity(); | ||
193 | } | 195 | } | ||
194 | } | 196 | } | ||
197 | } | ||||
195 | 198 | | |||
196 | void TextBlock::unwrapLine(int line, TextBlock *previousBlock, int fixStartLinesStartIndex) | 199 | void TextBlock::unwrapLine(int line, TextBlock *previousBlock, int fixStartLinesStartIndex) | ||
197 | { | 200 | { | ||
198 | // calc internal line | 201 | // calc internal line | ||
199 | line = line - startLine(); | 202 | line = line - startLine(); | ||
200 | 203 | | |||
201 | // two possiblities: either first line of this block or later line | 204 | // two possiblities: either first line of this block or later line | ||
202 | if (line == 0) { | 205 | if (line == 0) { | ||
Show All 38 Lines | |||||
241 | 244 | | |||
242 | // no cursors in this block and the previous one, no work to do.. | 245 | // no cursors in this block and the previous one, no work to do.. | ||
243 | if (m_cursors.empty() && previousBlock->m_cursors.empty()) { | 246 | if (m_cursors.empty() && previousBlock->m_cursors.empty()) { | ||
244 | return; | 247 | return; | ||
245 | } | 248 | } | ||
246 | 249 | | |||
247 | // move all cursors because of the unwrapped line | 250 | // move all cursors because of the unwrapped line | ||
248 | // remember all ranges modified | 251 | // remember all ranges modified | ||
249 | QSet<TextRange *> changedRanges; | 252 | std::vector<TextRange *> changedRanges; | ||
250 | foreach (TextCursor *cursor, m_cursors) { | 253 | foreach (TextCursor *cursor, m_cursors) { | ||
251 | // this is the unwrapped line | 254 | // this is the unwrapped line | ||
252 | if (cursor->lineInBlock() == 0) { | 255 | if (cursor->lineInBlock() == 0) { | ||
253 | // patch column | 256 | // patch column | ||
254 | cursor->m_column += oldSizeOfPreviousLine; | 257 | cursor->m_column += oldSizeOfPreviousLine; | ||
255 | 258 | | |||
256 | // remember range, if any | 259 | // remember range, if any | ||
257 | if (cursor->kateRange()) { | 260 | if (cursor->kateRange()) { | ||
258 | changedRanges.insert(cursor->kateRange()); | 261 | cursor->kateRange()->setValidityCheckRequired(); | ||
262 | changedRanges.push_back(cursor->kateRange()); | ||||
259 | } | 263 | } | ||
260 | } | 264 | } | ||
261 | } | 265 | } | ||
262 | 266 | | |||
263 | // move cursors of the moved line from previous block to this block now | 267 | // move cursors of the moved line from previous block to this block now | ||
264 | QSet<TextCursor *> newPreviousCursors; | 268 | QSet<TextCursor *> newPreviousCursors; | ||
265 | foreach (TextCursor *cursor, previousBlock->m_cursors) { | 269 | foreach (TextCursor *cursor, previousBlock->m_cursors) { | ||
266 | if (cursor->lineInBlock() == lastLineOfPreviousBlock) { | 270 | if (cursor->lineInBlock() == lastLineOfPreviousBlock) { | ||
267 | cursor->m_line = 0; | 271 | cursor->m_line = 0; | ||
268 | cursor->m_block = this; | 272 | cursor->m_block = this; | ||
269 | m_cursors.insert(cursor); | 273 | m_cursors.insert(cursor); | ||
270 | 274 | | |||
271 | // remember range, if any | 275 | // remember range, if any | ||
272 | if (cursor->kateRange()) { | 276 | if (cursor->kateRange()) { | ||
273 | changedRanges.insert(cursor->kateRange()); | 277 | cursor->kateRange()->setValidityCheckRequired(); | ||
278 | changedRanges.push_back(cursor->kateRange()); | ||||
274 | } | 279 | } | ||
275 | } else { | 280 | } else { | ||
276 | newPreviousCursors.insert(cursor); | 281 | newPreviousCursors.insert(cursor); | ||
277 | } | 282 | } | ||
278 | } | 283 | } | ||
279 | previousBlock->m_cursors = newPreviousCursors; | 284 | previousBlock->m_cursors = newPreviousCursors; | ||
280 | 285 | | |||
281 | // fixup the ranges that might be effected, because they moved from last line to this block | 286 | // fixup the ranges that might be effected, because they moved from last line to this block | ||
282 | foreach (TextRange *range, changedRanges) { | 287 | // we might need to invalidate ranges or notify about their changes | ||
288 | for (TextRange *range : changedRanges) { | ||||
This loop now crash in the unit test ./bin/bug313759 )It works again, if I use a QSet, at that one location. cullmann: This loop now crash in the unit test
./bin/bug313759
=)
It works again, if I use a QSet, at… | |||||
Ok, doesn't work due to the issue that we might delete the range via notifier in checkValidity() :P cullmann: Ok, doesn't work due to the issue that we might delete the range via notifier in checkValidity… | |||||
Noob question: Would QPointer help? if (range && range->isValidityCheckRequired()) { loh.tar: Noob question: Would QPointer help?
if (range && range->isValidityCheckRequired()) { | |||||
As it is no QObject, no ;=) Actually, I think all workaround might be even more expensive than the QSet. cullmann: As it is no QObject, no ;=) Actually, I think all workaround might be even more expensive than… | |||||
289 | if (range->isValidityCheckRequired()) { | ||||
283 | // update both blocks | 290 | // update both blocks | ||
284 | updateRange(range); | 291 | updateRange(range); | ||
285 | previousBlock->updateRange(range); | 292 | previousBlock->updateRange(range); | ||
286 | } | | |||
287 | 293 | | |||
288 | // check validity of all ranges, might invalidate them... | 294 | // afterwards check validity | ||
289 | foreach (TextRange *range, changedRanges) { | | |||
290 | range->checkValidity(); | 295 | range->checkValidity(); | ||
291 | } | 296 | } | ||
297 | } | ||||
292 | 298 | | |||
293 | // be done | 299 | // be done | ||
294 | return; | 300 | return; | ||
295 | } | 301 | } | ||
296 | 302 | | |||
297 | // easy: just move text to previous line and remove current one | 303 | // easy: just move text to previous line and remove current one | ||
298 | const int oldSizeOfPreviousLine = m_lines.at(line - 1)->length(); | 304 | const int oldSizeOfPreviousLine = m_lines.at(line - 1)->length(); | ||
299 | const int sizeOfCurrentLine = m_lines.at(line)->length(); | 305 | const int sizeOfCurrentLine = m_lines.at(line)->length(); | ||
Show All 28 Lines | |||||
328 | 334 | | |||
329 | // no cursors in this block, no work to do.. | 335 | // no cursors in this block, no work to do.. | ||
330 | if (m_cursors.empty()) { | 336 | if (m_cursors.empty()) { | ||
331 | return; | 337 | return; | ||
332 | } | 338 | } | ||
333 | 339 | | |||
334 | // move all cursors because of the unwrapped line | 340 | // move all cursors because of the unwrapped line | ||
335 | // remember all ranges modified | 341 | // remember all ranges modified | ||
336 | QSet<TextRange *> changedRanges; | 342 | std::vector<TextRange *> changedRanges; | ||
337 | foreach (TextCursor *cursor, m_cursors) { | 343 | foreach (TextCursor *cursor, m_cursors) { | ||
338 | // skip cursors in lines in front of removed one | 344 | // skip cursors in lines in front of removed one | ||
339 | if (cursor->lineInBlock() < line) { | 345 | if (cursor->lineInBlock() < line) { | ||
340 | continue; | 346 | continue; | ||
341 | } | 347 | } | ||
342 | 348 | | |||
343 | // this is the unwrapped line | 349 | // this is the unwrapped line | ||
344 | if (cursor->lineInBlock() == line) { | 350 | if (cursor->lineInBlock() == line) { | ||
345 | // patch column | 351 | // patch column | ||
346 | cursor->m_column += oldSizeOfPreviousLine; | 352 | cursor->m_column += oldSizeOfPreviousLine; | ||
347 | } | 353 | } | ||
348 | 354 | | |||
349 | // patch line of cursor | 355 | // patch line of cursor | ||
350 | cursor->m_line--; | 356 | cursor->m_line--; | ||
351 | 357 | | |||
352 | // remember range, if any | 358 | // remember range, if any | ||
353 | if (cursor->kateRange()) { | 359 | if (cursor->kateRange()) { | ||
354 | changedRanges.insert(cursor->kateRange()); | 360 | cursor->kateRange()->setValidityCheckRequired(); | ||
361 | changedRanges.push_back(cursor->kateRange()); | ||||
355 | } | 362 | } | ||
356 | } | 363 | } | ||
357 | 364 | | |||
358 | // check validity of all ranges, might invalidate them... | 365 | // we might need to invalidate ranges or notify about their changes | ||
359 | foreach (TextRange *range, changedRanges) { | 366 | for (TextRange *range : changedRanges) { | ||
367 | if (range->isValidityCheckRequired()) { | ||||
360 | range->checkValidity(); | 368 | range->checkValidity(); | ||
361 | } | 369 | } | ||
362 | } | 370 | } | ||
371 | } | ||||
363 | 372 | | |||
364 | void TextBlock::insertText(const KTextEditor::Cursor &position, const QString &text) | 373 | void TextBlock::insertText(const KTextEditor::Cursor &position, const QString &text) | ||
365 | { | 374 | { | ||
366 | // calc internal line | 375 | // calc internal line | ||
367 | int line = position.line() - startLine(); | 376 | int line = position.line() - startLine(); | ||
368 | 377 | | |||
369 | // get text | 378 | // get text | ||
370 | QString &textOfLine = m_lines.at(line)->textReadWrite(); | 379 | QString &textOfLine = m_lines.at(line)->textReadWrite(); | ||
Show All 18 Lines | |||||
389 | 398 | | |||
390 | // no cursors in this block, no work to do.. | 399 | // no cursors in this block, no work to do.. | ||
391 | if (m_cursors.empty()) { | 400 | if (m_cursors.empty()) { | ||
392 | return; | 401 | return; | ||
393 | } | 402 | } | ||
394 | 403 | | |||
395 | // move all cursors on the line which has the text inserted | 404 | // move all cursors on the line which has the text inserted | ||
396 | // remember all ranges modified | 405 | // remember all ranges modified | ||
397 | QSet<TextRange *> changedRanges; | 406 | std::vector<TextRange *> changedRanges; | ||
398 | foreach (TextCursor *cursor, m_cursors) { | 407 | foreach (TextCursor *cursor, m_cursors) { | ||
399 | // skip cursors not on this line! | 408 | // skip cursors not on this line! | ||
400 | if (cursor->lineInBlock() != line) { | 409 | if (cursor->lineInBlock() != line) { | ||
401 | continue; | 410 | continue; | ||
402 | } | 411 | } | ||
403 | 412 | | |||
404 | // skip cursors with too small column | 413 | // skip cursors with too small column | ||
405 | if (cursor->column() <= position.column()) { | 414 | if (cursor->column() <= position.column()) { | ||
406 | if (cursor->column() < position.column() || !cursor->m_moveOnInsert) { | 415 | if (cursor->column() < position.column() || !cursor->m_moveOnInsert) { | ||
407 | continue; | 416 | continue; | ||
408 | } | 417 | } | ||
409 | } | 418 | } | ||
410 | 419 | | |||
411 | // patch column of cursor | 420 | // patch column of cursor | ||
412 | if (cursor->m_column <= oldLength) { | 421 | if (cursor->m_column <= oldLength) { | ||
413 | cursor->m_column += text.size(); | 422 | cursor->m_column += text.size(); | ||
414 | } | 423 | } | ||
415 | 424 | | |||
416 | // special handling if cursor behind the real line, e.g. non-wrapping cursor in block selection mode | 425 | // special handling if cursor behind the real line, e.g. non-wrapping cursor in block selection mode | ||
417 | else if (cursor->m_column < textOfLine.size()) { | 426 | else if (cursor->m_column < textOfLine.size()) { | ||
418 | cursor->m_column = textOfLine.size(); | 427 | cursor->m_column = textOfLine.size(); | ||
419 | } | 428 | } | ||
420 | 429 | | |||
421 | // remember range, if any | 430 | // we only need to trigger checkValidity later if the range has feedback or might be invalidated | ||
422 | if (cursor->kateRange()) { | 431 | if (cursor->kateRange() && (cursor->kateRange()->feedback() || cursor->kateRange()->start().line() == cursor->kateRange()->end().line())) { | ||
423 | changedRanges.insert(cursor->kateRange()); | 432 | cursor->kateRange()->setValidityCheckRequired(); | ||
433 | changedRanges.push_back(cursor->kateRange()); | ||||
424 | } | 434 | } | ||
425 | } | 435 | } | ||
426 | 436 | | |||
427 | // check validity of all ranges, might invalidate them... | 437 | // we might need to invalidate ranges or notify about their changes | ||
428 | foreach (TextRange *range, changedRanges) { | 438 | for (TextRange *range : changedRanges) { | ||
439 | if (range->isValidityCheckRequired()) { | ||||
429 | range->checkValidity(); | 440 | range->checkValidity(); | ||
430 | } | 441 | } | ||
431 | } | 442 | } | ||
443 | } | ||||
432 | 444 | | |||
433 | void TextBlock::removeText(const KTextEditor::Range &range, QString &removedText) | 445 | void TextBlock::removeText(const KTextEditor::Range &range, QString &removedText) | ||
434 | { | 446 | { | ||
435 | // calc internal line | 447 | // calc internal line | ||
436 | int line = range.start().line() - startLine(); | 448 | int line = range.start().line() - startLine(); | ||
437 | 449 | | |||
438 | // get text | 450 | // get text | ||
439 | QString &textOfLine = m_lines.at(line)->textReadWrite(); | 451 | QString &textOfLine = m_lines.at(line)->textReadWrite(); | ||
Show All 23 Lines | |||||
463 | 475 | | |||
464 | // no cursors in this block, no work to do.. | 476 | // no cursors in this block, no work to do.. | ||
465 | if (m_cursors.empty()) { | 477 | if (m_cursors.empty()) { | ||
466 | return; | 478 | return; | ||
467 | } | 479 | } | ||
468 | 480 | | |||
469 | // move all cursors on the line which has the text removed | 481 | // move all cursors on the line which has the text removed | ||
470 | // remember all ranges modified | 482 | // remember all ranges modified | ||
471 | QSet<TextRange *> changedRanges; | 483 | std::vector<TextRange *> changedRanges; | ||
472 | foreach (TextCursor *cursor, m_cursors) { | 484 | foreach (TextCursor *cursor, m_cursors) { | ||
473 | // skip cursors not on this line! | 485 | // skip cursors not on this line! | ||
474 | if (cursor->lineInBlock() != line) { | 486 | if (cursor->lineInBlock() != line) { | ||
475 | continue; | 487 | continue; | ||
476 | } | 488 | } | ||
477 | 489 | | |||
478 | // skip cursors with too small column | 490 | // skip cursors with too small column | ||
479 | if (cursor->column() <= range.start().column()) { | 491 | if (cursor->column() <= range.start().column()) { | ||
480 | continue; | 492 | continue; | ||
481 | } | 493 | } | ||
482 | 494 | | |||
483 | // patch column of cursor | 495 | // patch column of cursor | ||
484 | if (cursor->column() <= range.end().column()) { | 496 | if (cursor->column() <= range.end().column()) { | ||
485 | cursor->m_column = range.start().column(); | 497 | cursor->m_column = range.start().column(); | ||
486 | } else { | 498 | } else { | ||
487 | cursor->m_column -= (range.end().column() - range.start().column()); | 499 | cursor->m_column -= (range.end().column() - range.start().column()); | ||
488 | } | 500 | } | ||
489 | 501 | | |||
490 | // remember range, if any | 502 | // we only need to trigger checkValidity later if the range has feedback or might be invalidated | ||
491 | if (cursor->kateRange()) { | 503 | if (cursor->kateRange() && (cursor->kateRange()->feedback() || cursor->kateRange()->start().line() == cursor->kateRange()->end().line())) { | ||
492 | changedRanges.insert(cursor->kateRange()); | 504 | cursor->kateRange()->setValidityCheckRequired(); | ||
505 | changedRanges.push_back(cursor->kateRange()); | ||||
493 | } | 506 | } | ||
494 | } | 507 | } | ||
495 | 508 | | |||
496 | // check validity of all ranges, might invalidate them... | 509 | // we might need to invalidate ranges or notify about their changes | ||
497 | foreach (TextRange *range, changedRanges) { | 510 | for (TextRange *range : changedRanges) { | ||
511 | if (range->isValidityCheckRequired()) { | ||||
498 | range->checkValidity(); | 512 | range->checkValidity(); | ||
499 | } | 513 | } | ||
500 | } | 514 | } | ||
515 | } | ||||
501 | 516 | | |||
502 | void TextBlock::debugPrint(int blockIndex) const | 517 | void TextBlock::debugPrint(int blockIndex) const | ||
503 | { | 518 | { | ||
504 | // print all blocks | 519 | // print all blocks | ||
505 | for (int i = 0; i < m_lines.size(); ++i) | 520 | for (int i = 0; i < m_lines.size(); ++i) | ||
506 | printf("%4d - %4d : %4d : '%s'\n", blockIndex, startLine() + i | 521 | printf("%4d - %4d : %4d : '%s'\n", blockIndex, startLine() + i | ||
507 | , m_lines.at(i)->text().size(), qPrintable(m_lines.at(i)->text())); | 522 | , m_lines.at(i)->text().size(), qPrintable(m_lines.at(i)->text())); | ||
508 | } | 523 | } | ||
▲ Show 20 Lines • Show All 217 Lines • Show Last 20 Lines |
You can use unordered_set, so you don't need m_isCheckValidityRequired any more. It can be applied to other places as well.