/* Copyright (c) 2006-2014 Jonas Fonseca <jonas.fonseca@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "tig/tig.h"
#include "tig/argv.h"
#include "tig/repo.h"
#include "tig/options.h"
#include "tig/view.h"
#include "tig/draw.h"
#include "tig/display.h"
/*
* Navigation
*/
bool
goto_view_line(struct view *view, unsigned long offset, unsigned long lineno)
{
if (lineno >= view->lines)
lineno = view->lines > 0 ? view->lines - 1 : 0;
if (offset > lineno || offset + view->height <= lineno) {
unsigned long half = view->height / 2;
if (lineno > half)
offset = lineno - half;
else
offset = 0;
}
if (offset != view->pos.offset || lineno != view->pos.lineno) {
view->pos.offset = offset;
view->pos.lineno = lineno;
return TRUE;
}
return FALSE;
}
/* Scrolling backend */
void
do_scroll_view(struct view *view, int lines)
{
bool redraw_current_line = FALSE;
/* The rendering expects the new offset. */
view->pos.offset += lines;
assert(0 <= view->pos.offset && view->pos.offset < view->lines);
assert(lines);
/* Move current line into the view. */
if (view->pos.lineno < view->pos.offset) {
view->pos.lineno = view->pos.offset;
redraw_current_line = TRUE;
} else if (view->pos.lineno >= view->pos.offset + view->height) {
view->pos.lineno = view->pos.offset + view->height - 1;
redraw_current_line = TRUE;
}
assert(view->pos.offset <= view->pos.lineno && view->pos.lineno < view->lines);
/* Redraw the whole screen if scrolling is pointless. */
if (view->height < ABS(lines)) {
redraw_view(view);
} else {
int line = lines > 0 ? view->height - lines : 0;
int end = line + ABS(lines);
scrollok(view->win, TRUE);
wscrl(view->win, lines);
scrollok(view->win, FALSE);
while (line < end && draw_view_line(view, line))
line++;
if (redraw_current_line)
draw_view_line(view, view->pos.lineno - view->pos.offset);
wnoutrefresh(view->win);
}
view->has_scrolled = TRUE;
report_clear();
}
/* Scroll frontend */
void
scroll_view(struct view *view, enum request request)
{
int lines = 1;
assert(view_is_displayed(view));
if (request == REQ_SCROLL_WHEEL_DOWN || request == REQ_SCROLL_WHEEL_UP)
lines = opt_mouse_scroll;
switch (request) {
case REQ_SCROLL_FIRST_COL:
view->pos.col = 0;
redraw_view_from(view, 0);
report_clear();
return;
case REQ_SCROLL_LEFT:
if (view->pos.col == 0) {
report("Cannot scroll beyond the first column");
return;
}
if (view->pos.col <= apply_step(opt_horizontal_scroll, view->width))
view->pos.col = 0;
else
view->pos.col -= apply_step(opt_horizontal_scroll, view->width);
redraw_view_from(view, 0);
report_clear();
return;
case REQ_SCROLL_RIGHT:
view->pos.col += apply_step(opt_horizontal_scroll, view->width);
redraw_view(view);
report_clear();
return;
case REQ_SCROLL_PAGE_DOWN:
lines =