| 62 | } |
| 63 | |
| 64 | ScriptLogView::Window ScriptLogView::window(void) |
| 65 | { |
| 66 | ScriptConsole& console = ScriptConsole::get(); |
| 67 | |
| 68 | Window w; |
| 69 | w.total = console.lineCount(); |
| 70 | if (w.total == 0) { |
| 71 | mRows.clear(); |
| 72 | return w; |
| 73 | } |
| 74 | |
| 75 | // Pinned to the tail unless the user scrolled back, so a talking script |
| 76 | // pushes the view along instead of scrolling out from under them. The |
| 77 | // scrollback is clamped again here rather than trusted: the console drops |
| 78 | // its oldest lines as it grows, which can move the tail under a scrollback |
| 79 | // that was in range when it was set. |
| 80 | const size_t maxFirst = w.total > (size_t)mViewport ? w.total - (size_t)mViewport : 0; |
| 81 | const size_t back = std::min((size_t)mScrollBack, maxFirst); |
| 82 | w.first = maxFirst - back; |
| 83 | |
| 84 | // Re-copy only when the content or the window actually moved. |
| 85 | const unsigned gen = console.generation(); |
| 86 | if (gen != mSeenGeneration || w.first != mSeenFirst || mRows.size() != (size_t)mViewport) { |
| 87 | console.copyWindow(w.first, (size_t)mViewport, mRows); |
| 88 | mSeenGeneration = gen; |
| 89 | mSeenFirst = w.first; |
| 90 | } |
| 91 | |
| 92 | // Scrollbar only once there is more than one screenful. maxFirst is then |
| 93 | // non-zero, so the travel fraction is safe to divide. |
| 94 | w.scrollbar = w.total > (size_t)mViewport; |
| 95 | if (w.scrollbar) { |
| 96 | w.thumbSpan = (float)mViewport / (float)w.total; |
| 97 | w.thumbTravel = (float)w.first / (float)maxFirst; |
| 98 | } |
| 99 | return w; |
| 100 | } |
no test coverage detected