// 30 november 2014

static void finishSelect(struct table *t, intptr_t prev)
{
	if (t->selected < 0)
		t->selected = 0;
	if (t->selected >= t->count)
		t->selected = t->count - 1;

	// always redraw the old and new rows to avoid artifacts when scrolling, even if they are the same (since the focused column may have changed)
	redrawRow(t, prev);
	if (prev != t->selected)
		redrawRow(t, t->selected);

	// if we need to scroll, the scrolling will force a redraw, so we don't have to worry about doing so ourselves
	if (t->selected < t->firstVisible)
		vscrollto(t, t->selected);
	// note that this is not lastVisible(t) because the last visible row may only be partially visible and we want selections to make them fully visible
	else if (t->selected >= (t->firstVisible + t->pagesize))
		vscrollto(t, t->selected - t->pagesize + 1);
}

// TODO isolate functionality so other keyboard event handlers can run
static void keySelect(struct table *t, WPARAM wParam, LPARAM lParam)
{
	intptr_t prev;

	// TODO figure out correct behavior with nothing selected
	if (t->count == 0)		// don't try to do anything if there's nothing to do
		return;
	prev = t->selected;
	switch (wParam) {
	case VK_UP:
		t->selected--;
		break;
	case VK_DOWN:
		t->selected++;
		break;
	case VK_PRIOR:
		t->selected -= t->pagesize;
		break;
	case VK_NEXT:
		t->selected += t->pagesize;
		break;
	case VK_HOME:
		t->selected = 0;
		break;
	case VK_END:
		t->selected = t->count - 1;
		break;
	case VK_LEFT:
		t->focusedColumn--;
		if (t->focusedColumn < 0)
			if (t->nColumns == 0)		// peg at -1
				t->focusedColumn = -1;
			else
				t->focusedColumn = 0;
		break;
	case VK_RIGHT:
		t->focusedColumn++;
		if (t->focusedColumn >= t->nColumns)
			if (t->nColumns == 0)		// peg at -1
				t->focusedColumn = -1;
			else
				t->focusedColumn = t->nColumns - 1;
		break;
	// TODO keyboard shortcuts for going to the first/last column?
	default:
		// don't touch anything
		return;
	}
	finishSelect(t, prev);
}

// TODO rename
static void selectItem(struct table *t, WPARAM wParam, LPARAM lParam)
{
	intptr_t prev;

	prev = t->selected;
	lParamToRowColumn(t, lParam, &(t->selected), &(t->focusedColumn));
	finishSelect(t, prev);
}