"Fossies" - the Fresh Open Source Software archive 
Member "cftp-0.12/fn_scroll.c" of archive cftp-0.12.tar.gz:
/*
$NiH: fn_scroll.c,v 1.22 2002/09/16 12:42:31 dillo Exp $
fn_scroll.c -- bindable functions: scrolling
Copyright (C) 1996-2002 Dieter Baron
This file is part of cftp, a fullscreen ftp client
The author can be contacted at <dillo@giga.or.at>
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <string.h>
#include "directory.h"
#include "bindings.h"
#include "functions.h"
#include "display.h"
#include "tty.h"
#include "list.h"
#include "loop.h"
#include "options.h"
void aux_scroll(int top, int sel, int force);
void aux_scroll_line(int n);
void aux_scroll_page(int n);
void
aux_scroll(int top, int sel, int force)
{
if (sel < 0)
sel = 0;
if (sel >= list->len)
sel = list->len -1;
if (top > sel)
top = sel;
if (top <= sel - win_lines)
top = sel - win_lines + 1;
if (top > list->len - win_lines)
top = list->len - win_lines;
if (top < 0)
top = 0;
list->top = top;
list->cur = sel;
if (force >= 0)
list_do(force);
}
void
aux_scroll_line(int n)
{
int sel, top;
if (n == 0 || list->len == 0)
return;
if (n > 0) {
if (opt_wrap)
sel = (list->cur+n) % list->len;
else
sel = list->cur+n;
if (list->top > sel || list->top <= sel-win_lines)
top = sel-win_lines+1;
else
top = list->top;
}
else {
if (opt_wrap) {
sel = list->cur-((-n) % list->len);
if (sel < 0)
sel += list->len;
}
else
sel = list->cur + n;
if (list->top > sel || list->top <= sel-win_lines)
top = sel;
else
top = list->top;
}
aux_scroll(top, sel, 0);
}
void
aux_scroll_page(int n)
{
int top;
if (n == 0)
return;
if (n > 0) {
if (list->cur == list->len-1) {
if (opt_wrap)
list->top = list->cur = 0;
else
return;
}
else if (list->top >= list->len - win_lines)
list->cur = list->len-1;
else {
top = list->top + n;
if (top > list->len) {
if (opt_wrap) {
list->cur = list->top
+ ((list->len-list->top)/win_lines)*win_lines;
list->top = list->len - win_lines;
}
else {
list->cur = list->len-1;
list->top = list->len - win_lines;
}
}
else if (top > list->len - win_lines) {
list->cur = top;
list->top = list->len - win_lines;
}
else
list->top = list->cur = top;
}
}
else if (n < 0) {
if (list->cur > list->top)
list->cur = list->top;
else if (list->top == 0) {
if (opt_wrap) {
list->top = list->len - win_lines;
if (list->top < 0)
list->top = 0;
list->cur = list->len-1;
}
else
return;
}
else {
/* XXX: inconsistent with forward scrolling */
top = list->top + n;
if (top < 0)
top = 0;
list->top = list->cur = top;
}
}
list_do(0);
}
void
fn_down(char **args)
{
aux_scroll_line(get_prefix_args(args, 1));
}
void
fn_up(char **args)
{
aux_scroll_line(-get_prefix_args(args, 1));
}
void
fn_pg_down(char **args)
{
aux_scroll_page(get_prefix_args(args, 1)*win_lines);
}
void
fn_pg_up(char **args)
{
aux_scroll_page(-get_prefix_args(args, 1)*win_lines);
}
void
fn_goto(char **args)
{
int n;
n = get_prefix_args(args, list->len)-1;
if (n == -1)
n = list->len-1;
aux_scroll(n-(win_lines/2), n, 0);
}
#define FN_IS_BACK 0x1
#define FN_IS_FAIL 0x2
#define FN_IS_WRAP 0x4
int
aux_isread(int state, char *s)
{
char b[2048];
sprintf(b, "%s%s%sI-search%s: %s",
(state & FN_IS_FAIL ? "Failing " : ""),
(state & FN_IS_WRAP ? (state & FN_IS_FAIL ? "w" : "W") : ""),
(state & FN_IS_WRAP ? "rapped " : ""),
(state & FN_IS_BACK ? " backward" : ""),
s);
return read_char(b);
}
void
fn_isearch(char **args)
{
char b[1024], *p;
int n, c, start, current, research, state, wrap;
state = 0;
if (args && strcmp(args[0], "-r") == 0) {
state = FN_IS_BACK;
}
b[0] = '\0';
p = b;
n = 0;
start = current = list->cur;
while ((c=aux_isread(state, b)) != '\n' && c != 7 /* ^G */) {
research = 1;
if (c == tty_verase) {
if (p > b) {
*(--p) = '\0';
current = start;
state &= ~FN_IS_WRAP;
}
else
research = 0;
}
else if (c == tty_vwerase) {
while (p>b && *(--p) == ' ')
;
while (p>b && *(p-1) != ' ')
--p;
*p = '\0';
current = start;
state &= ~FN_IS_WRAP;
}
else if (c == tty_vkill) {
p = b;
*p = '\0';
current = start;
state &= ~FN_IS_WRAP;
}
else if (c == 19 /* ^S */) {
if ((state & FN_IS_FAIL) && !(state & FN_IS_BACK))
state |= FN_IS_WRAP;
state &= ~FN_IS_BACK;
research = 2;
}
else if (c == 18 /* ^R */) {
if ((state & FN_IS_FAIL) && (state & FN_IS_BACK))
state |= FN_IS_WRAP;
state |= FN_IS_BACK;
research = 2;
}
else if (c == 12 /* ^L */) {
disp_redraw();
research = 0;
}
else if (c >= 32 && c < 127) {
*(p++) = c;
*p = '\0';
}
else {
loop_putkey(c);
return;
}
if (research) {
n = current;
state &= ~FN_IS_FAIL;
if (!(state & FN_IS_BACK)) {
if (research == 2)
n++;
wrap = 0;
while (!(state & FN_IS_FAIL)) {
if (wrap && n == current+1) {
state |= FN_IS_FAIL;
break;
}
if (n >= list->len) {
if (state & FN_IS_WRAP) {
wrap = 1;
n = 0;
}
else {
state |= FN_IS_FAIL;
break;
}
}
if (strstr(LIST_LINE(list, n)->name, b) != NULL)
break;
n++;
}
}
else {
if (research == 2)
--n;
wrap = 0;
while (!(state & FN_IS_FAIL)) {
if (wrap && n == current-1) {
state |= FN_IS_FAIL;
break;
}
if (n < 0) {
if (state & FN_IS_WRAP) {
n = list->len-1;
wrap = 1;
}
else {
state |= FN_IS_FAIL;
break;
}
}
if (strstr(LIST_LINE(list, n)->name, b) != NULL)
break;
--n;
}
}
}
if (!(state & FN_IS_FAIL)) {
current = n;
if (current >= list->top && current < list->top+win_lines)
aux_scroll(list->top, current, 0);
else
aux_scroll(current-(win_lines/2), current, 0);
}
}
if (c == 7 /* ^G */) {
if (start >= list->top && start < list->top+win_lines)
aux_scroll(list->top, start, 0);
else
aux_scroll(start-(win_lines/2), start, 0);
}
disp_status(DISP_STATUS, "");
return;
}