"Fossies" - the Fresh Open Source Software archive 
Member "cftp-0.12/list.c" of archive cftp-0.12.tar.gz:
/*
$NiH: list.c,v 1.20 2002/09/17 11:59:46 dillo Exp $
list.c -- display lists
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 <stdlib.h>
#include <string.h>
#include "display.h"
#include "list.h"
#include "tty.h"
#include "options.h"
#include "bindings.h"
#include "status.h"
struct list *list;
enum list_scrolltype { LIST_SCNONE, LIST_SCLINE, LIST_SCREGION };
enum list_scrolltype list_scrolltype;
static struct list *last_list;
static int last_top, last_sel;
void list_full(struct list *list);
void list_region(struct list *list, int up, int n);
void list_scroll(struct list *list, int up, int n);
void list_refill(struct list *list, int st, int n, int clreolp);
void list_desel(struct list *list, int top, int sel);
void list_sel(struct list *list);
void list_line(struct list *list, int i, int selp, int clreolp);
void
list_do(int full)
{
int up, n, per;
if (disp_quiet ||
(!full && list->top == last_top && list->cur == last_sel))
return;
if (list != last_list) {
full = 1;
last_list = list;
}
if (list->len <= win_lines)
per = -1;
else
per = (list->top*100)/(list->len-win_lines);
if (per != status.percent) {
status.percent = per;
status_do(bs_none);
}
if (full || abs(last_top-list->top) >= win_lines-opt_scrlimit) {
list_full(list);
}
else if (last_top != list->top) {
if (last_sel >= list->top && last_sel < list->top+win_lines
&& list_scrolltype)
list_desel(list, last_top, last_sel);
if (list->top < last_top) {
up = 0;
n = last_top - list->top;
}
else {
up = 1;
n = list->top - last_top;
}
switch (list_scrolltype) {
case LIST_SCREGION:
list_region(list, up, n);
break;
case LIST_SCLINE:
list_scroll(list, up, n);
break;
case LIST_SCNONE:
list_full(list);
break;
}
if (list->cur >= last_top && list->cur < last_top+win_lines
&& list_scrolltype)
list_sel(list);
}
else {
list_desel(list, last_top, last_sel);
list_sel(list);
}
last_top = list->top;
last_sel = list->cur;
}
void
list_full(struct list *list)
{
int i;
if (!*TTY_CAP(ce)) {
tty_goto(0, win_top);
tty_clreos(win_lines+2);
status_do(bs_none);
disp_restat();
}
tty_goto(0, win_top);
list_refill(list, list->top, win_lines, *TTY_CAP(ce));
if (*TTY_CAP(ce))
for (i=list->len; i<win_lines; i++) {
tty_clreol();
putc('\n', stdout);
}
}
void
list_region(struct list *list, int up, int n)
{
/*
if (up)
tty_goto(0, win_bottom);
else
tty_goto(0, win_top);
*/
tty_scregion(win_top, win_bottom);
if (up) {
tty_goto(0, win_bottom);
tty_scrollup(n, win_lines);
tty_scregion(0, tty_lines-1);
tty_goto(0, win_bottom-n+1);
list_refill(list, list->top+win_lines-n, n, 0);
}
else {
tty_goto(0, win_top);
tty_scrolldown(n, win_lines);
tty_scregion(0, tty_lines-1);
tty_goto(0, win_top);
list_refill(list, list->top, n, 0);
}
tty_lowleft();
}
void
list_scroll(struct list *list, int up, int n)
{
if (up) {
tty_goto(0, win_top);
tty_dellines(n, win_lines+2);
tty_goto(0, win_bottom+1);
tty_clreos(2);
tty_goto(0, win_lines-n+1);
list_refill(list, list->top+win_lines-n, n, 0);
}
else {
tty_goto(0, win_top);
tty_inslines(n, win_lines+2);
tty_goto(0, win_bottom+1);
tty_clreos(2);
tty_goto(0, win_top);
list_refill(list, list->top, n, 0);
}
disp_restat();
}
void
list_refill(struct list *list, int top, int n, int clreolp)
{
int i, end;
end = top+n;
for (i=top; i<end && i<list->len; i++)
list_line(list, i, list->cur == i, clreolp);
}
void
list_desel(struct list *list, int top, int sel)
{
tty_goto(0, win_top+sel-top);
list_line(list, sel, 0, 0);
}
void
list_sel(struct list *list)
{
tty_goto(0, win_top+list->cur-list->top);
list_line(list, list->cur, 1, 0);
}
void
list_line(struct list *list, int i, int selp, int clreolp)
{
int l, cols;
char *s, save;
s = LIST_LINE(list, i)->line;
l = strlen(s);
cols = tty_cols;
if (selp)
tty_standout();
if (l < cols) {
fputs(s, stdout);
if (selp)
tty_standend();
if (clreolp)
tty_clreol();
putc('\n', stdout);
}
else {
save = s[cols];
s[cols] = '\0';
switch (tty_am) {
case TTY_AMNONE:
case TTY_AMXN:
puts(s);
break;
case TTY_AM:
fputs(s, stdout);
}
s[cols] = save;
if (selp)
tty_standend();
}
}
void
list_init(void)
{
last_list = NULL;
if (*TTY_CAP(cs))
list_scrolltype = LIST_SCREGION;
else if ((*TTY_CAP(AL) || *TTY_CAP(al)) && (*TTY_CAP(DL) || *TTY_CAP(dl)))
list_scrolltype = LIST_SCLINE;
else
list_scrolltype = LIST_SCNONE;
}
void
list_reline(int n)
{
if (n < last_top || n > last_top+win_lines)
return;
tty_goto(0, win_top+n-last_top);
list_line(last_list, n, (n == last_sel), 0);
}