home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
180.lha
/
Files_v1.2
/
src
/
files.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-04-28
|
14KB
|
670 lines
/*
* FILES.C
*
* File Manager!
*
* (c)Copyright 1987 Matthew Dillon, All Rights Reserved.
*/
#include "files.h"
extern LOCK *Lock();
extern LOCK *ParentDir(), *CurrentDir();
extern void *malloc();
extern void addentry();
RECORD *Rbase; /* All entries */
RECORD *DisplayTop; /* Entry at the display top */
RECORD *Highlighted; /* Highlighted entry */
short MaxNameLen;
long NumEntries;
long NumSelected;
long NumTop;
long NewNumTop;
FIB *Fib;
short Modified;
short Xs, Xe, Ys, Ye, Rows, Cols;
char Title[80];
redisplay(newtop)
{
short i;
short noscroll = 0;
uword percent, fill;
RECORD *rec;
bigboxbounds(&Xs,&Xe,&Ys,&Ye);
Rows = (Ye-Ys)/Rp->TxHeight;
Cols = (Xe-Xs)/Rp->TxWidth;
if (newtop) {
long delta = NumTop - NewNumTop;
if (delta < 0)
delta = -delta;
if (delta >= Rows)
noscroll = 1;
}
while (DisplayTop && !(DisplayTop->flags & R_SELECTED))
DisplayTop = DisplayTop->next;
if (newtop) {
while (NewNumTop != NumTop && DisplayTop) {
if (NewNumTop < NumTop) {
do {
DisplayTop = DisplayTop->prev;
} while (DisplayTop && !(DisplayTop->flags & R_SELECTED));
--NumTop;
if (DisplayTop && !noscroll) {
ScrollRaster(Rp, 0, -Rp->TxHeight, Xs, Ys, Xe-1, Ye-1);
displayat(DisplayTop, 0);
}
} else {
do {
DisplayTop = DisplayTop->next;
} while (DisplayTop && !(DisplayTop->flags & R_SELECTED));
++NumTop;
if (DisplayTop && !noscroll) {
ScrollRaster(Rp, 0, Rp->TxHeight, Xs, Ys, Xe-1, Ye-1);
displayrow(Rows-1);
}
}
}
if (DisplayTop && !noscroll)
return(0);
}
sprintf(Title, "%ld/%ld", NumSelected, NumEntries);
title(Title);
if (DisplayTop == NULL) {
DisplayTop = Rbase;
NumTop = 0;
}
if (!newtop) {
percent = fill = 0xFFFF;
if (NumSelected) {
if (NumTop+(Rows>>1) > NumSelected)
percent = 0xFFFF;
else
percent = (NumTop + (Rows>>1)) * 0xFFFF / NumSelected;
fill = Rows * 0xFFFF / NumSelected;
if (Rows > NumSelected)
fill = 0xFFFF;
}
setslider(percent, fill);
}
SetAPen(Rp, 0);
RectFill(Rp, Xs, Ys, Xe-1, Ye-1);
SetAPen(Rp, 1);
for (rec = DisplayTop, i = 0; rec && i < Rows; rec = rec->next) {
if (!(rec->flags & R_SELECTED))
continue;
displayat(rec, i);
++i;
}
}
redisplayone(rec)
RECORD *rec;
{
RECORD *nrec;
short i;
for (i = 0, nrec = DisplayTop; nrec && i < Rows; nrec = nrec->next) {
if (!(nrec->flags & R_SELECTED))
continue;
if (nrec == rec)
break;
++i;
}
if (i < Rows && nrec == rec) {
SetAPen(Rp, 0);
RectFill(Rp, Xs, Ys + (Rp->TxHeight*i), Xe-1, Ys + (Rp->TxHeight*i) + Rp->TxHeight - 1);
SetAPen(Rp, 1);
displayat(rec, i);
}
}
displayrow(row)
{
register RECORD *rec = DisplayTop;
register short i = row;
while (i && rec) {
rec = rec->next;
while (rec && !(rec->flags & R_SELECTED))
rec = rec->next;
--i;
}
if (rec && row < Rows)
displayat(rec, row);
}
displayat(rec, i)
RECORD *rec;
{
short len;
len = strlen(rec->name);
if (len > Cols)
len = Cols;
if (rec == Highlighted) {
SetAPen(Rp, 0);
SetBPen(Rp, 1);
}
Move(Rp, Xs, Ys + (Rp->TxHeight*i) + Rp->TxBaseline);
Text(Rp, rec->name, len);
if (Cols > MaxNameLen && rec->comment) {
len = strlen(rec->comment);
if (len > Cols - MaxNameLen)
len = Cols - MaxNameLen;
Move(Rp, Xs + MaxNameLen * Rp->TxWidth, Ys + (Rp->TxHeight * i) + Rp->TxBaseline);
Text(Rp, rec->comment, len);
}
if (rec == Highlighted) {
SetAPen(Rp, 1);
SetBPen(Rp, 0);
}
}
bigboxhit(y, up)
{
RECORD *hl = Highlighted;
short row;
Highlighted = NULL;
if (hl)
redisplayone(hl);
row = (y - Ys) / Rp->TxHeight;
if (row >= Rows || Rows < 0)
return(0);
for (hl = DisplayTop; hl && !(hl->flags & R_SELECTED); hl = hl->next);
while (hl && row) {
if (hl->flags & R_SELECTED)
--row;
hl = hl->next;
}
for (; hl && !(hl->flags & R_SELECTED); hl = hl->next);
if (Highlighted = hl) {
redisplayone(hl);
setcomment((hl->comment) ? hl->comment : "");
if (up)
activate_com();
}
}
sliderhit()
{
uword pos, fill;
getsliderpos(&pos, &fill);
NewNumTop = pos * (NumSelected - Rows + 1) / 0xFFFF;
redisplay(1);
}
/*
* Add a disk volume to the list. Determine
* the root and add entries beginning at the
* specification.
*/
void
add_volume(str)
char *str;
{
LOCK *lock;
char path[128];
int len;
Highlighted = NULL;
Fib = malloc(sizeof(FIB));
if (Fib == NULL)
return;
resetsort(); /* also cleans up the database */
path[0] = 0;
if (lock = Lock(str, ACCESS_READ)) {
if (Examine(lock, Fib)) {
buildpath(lock, path);
len = strlen(path);
if (path[len-1] == ':' || path[len-1] == '/') {
path[len] = '*';
path[len+1] = 0;
select_pattern(path, 1);
path[len] = 0;
}
Examine(lock, Fib);
if (Fib->fib_DirEntryType < 0) {
addentry(path, Fib->fib_Comment, Fib->fib_Size);
} else {
RECORD *base;
/* find start of killpatterns, if any */
for (base = Rbase; base; base = base->next) {
if (strcmp(base->name, KILLNAME) < 0)
continue;
break;
}
title("Wait.. Scanning");
scandir(lock, path, base);
}
title("Wait.. Update");
rem_selected(NULL, 1);
}
UnLock(lock);
}
free(Fib);
strcat(path, "*");
title("Select path");
select_pattern(path, 0);
}
buildpath(lock, path)
LOCK *lock;
char *path;
{
LOCK *parent;
short plen, nlen;
plen = strlen(path);
nlen = strlen(Fib->fib_FileName) + 1;
if (nlen == 1) { /* RAM: */
strcpy(Fib->fib_FileName, "ram");
nlen = 4;
}
bmov(path, path + nlen, plen + 1);
strcpy(path, Fib->fib_FileName);
if (Fib->fib_DirEntryType >= 0)
path[nlen-1] = '/';
if (parent = ParentDir(lock)) {
if (Examine(parent, Fib)) {
buildpath(parent, path);
}
UnLock(parent);
} else {
path[nlen-1] = ':';
}
}
scandir(lock, path, base)
LOCK *lock;
char *path;
RECORD *base;
{
short restorelen = strlen(path);
short len = restorelen;
LOCK *olddirlock;
if (path[restorelen-1] != ':' && path[restorelen-1] != '/') {
strcpy(path + restorelen, "/");
++len;
}
olddirlock = CurrentDir(lock);
if (notkilled(path, base))
addentry(path, Fib->fib_Comment, Fib->fib_Size);
while (ExNext(lock, Fib)) {
strcpy(path+len, Fib->fib_FileName);
if (Fib->fib_DirEntryType < 0) {
if (notkilled(path, base))
addentry(path, Fib->fib_Comment, Fib->fib_Size);
} else {
LOCK *lock = Lock(Fib->fib_FileName, ACCESS_READ);
if (lock) {
FIB *oldfib = Fib;
if (Fib = malloc(sizeof(FIB))) {
Examine(lock, Fib);
scandir(lock, path, base);
UnLock(lock);
free(Fib);
}
Fib = oldfib;
}
}
}
CurrentDir(olddirlock);
path[restorelen] = 0;
}
notkilled(path,base)
char *path;
RECORD *base;
{
while (base && strcmp(base->name, KILLNAME) == 0) {
if (base->comment && newwildcmp(base->comment, path))
return(0);
base = base->next;
}
return(1);
}
load_database(fi)
FILE *fi;
{
char name[132];
char comm[132];
char size[32];
fgets(name, 128, fi); /* # entries per item */
Highlighted = NULL;
resetsort();
title("Wait... Loading");
while (fgets(name, 128, fi) && fgets(comm, 128, fi) && fgets(size, 32, fi)) {
name[strlen(name)-1] = 0; /* remove newlines */
comm[strlen(comm)-1] = 0;
addentry(name, comm, atoi(size));
}
rem_selected(NULL, 1);
selectall();
redisplay(0);
}
save_database(fi)
FILE *fi;
{
RECORD *rec;
char buf[32];
cleanup();
title("Saving...");
fputs("3\n", fi);
for (rec = Rbase; rec; rec = rec->next) {
fwrite(rec->name, strlen(rec->name), 1, fi);
putc('\n', fi);
if (rec->comment)
fwrite(rec->comment, strlen(rec->comment), 1, fi);
putc('\n', fi);
sprintf(buf, "%ld\n", rec->bytes);
fputs(buf, fi);
if (ferror(fi))
break;
}
}
selectall()
{
RECORD *rec;
short len;
Highlighted = NULL;
DisplayTop = NULL;
MaxNameLen = 0;
for (rec = Rbase; rec; rec = rec->next) {
if (rec->flags & R_KILLPAT)
continue;
len = strlen(rec->name);
if (MaxNameLen <= len)
MaxNameLen = len + 1;
rec->flags |= R_SELECTED;
}
NumSelected = NumEntries;
}
select_pattern(str, noref)
char *str;
{
register RECORD *rec;
register short len;
short which = 0;
if (*str == '+') /* ADD selected patterns */
++str, which = 1;
if (*str == '-') /* REMOVE selected patterns*/
++str, which = 2;
DisplayTop = NULL;
Highlighted= NULL;
switch(which) {
case 0:
NumSelected = 0;
MaxNameLen = 0;
for (rec = Rbase; rec; rec = rec->next) {
rec->flags &= ~R_SELECTED;
if (rec->flags & R_KILLPAT)
continue;
if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) {
if (noref) {
rec->flags |= R_UPDATE;
} else {
rec->flags |= R_SELECTED;
++NumSelected;
if ((len = strlen(rec->name)) >= MaxNameLen)
MaxNameLen = len + 1;
}
}
}
break;
case 1:
for (rec = Rbase; rec; rec = rec->next) {
if ((rec->flags & R_KILLPAT) || (rec->flags & R_SELECTED))
continue;
if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) {
rec->flags |= R_SELECTED;
++NumSelected;
if ((len = strlen(rec->name)) >= MaxNameLen)
MaxNameLen = len + 1;
}
}
break;
case 2:
for (rec = Rbase; rec; rec = rec->next) {
if (!(rec->flags & R_SELECTED))
continue;
if (newwildcmp(str, rec->name) || (rec->comment && newwildcmp(str, rec->comment))) {
rec->flags &= ~R_SELECTED;
--NumSelected;
}
}
break;
}
if (!noref)
redisplay(0);
}
/*
* If onerec != NULL, remove the one record,
* else remove all SELECTED records.
*/
rem_selected(onerec, noref)
RECORD *onerec;
{
register RECORD *rec;
register long len, maxlen;
Highlighted = NULL;
cleanup();
if (onerec) {
if (onerec->flags & R_SELECTED) {
onerec->flags &= ~R_SELECTED;
--NumSelected;
}
onerec->flags |= R_KILLPAT;
--NumEntries;
} else {
maxlen = 0;
for (rec = Rbase; rec; rec = rec->next) {
if (noref) {
if (rec->flags & R_UPDATE) {
rec->flags &= ~R_UPDATE;
rec->flags |= R_KILLPAT;
--NumEntries;
}
} else {
if (rec->flags & R_SELECTED) {
rec->flags &= ~R_SELECTED;
rec->flags |= R_KILLPAT;
--NumEntries;
}
}
if (!(rec->flags & R_KILLPAT) && (len=strlen(rec->name)) > maxlen)
maxlen = len;
}
if (!noref)
NumSelected = 0;
MaxNameLen = maxlen+1;
}
if (noref)
cleanup();
else
redisplay(0);
}
undo()
{
RECORD *rec;
Highlighted = NULL;
for (rec = Rbase; rec; rec = rec->next) {
if (rec->flags & R_KILLPAT) {
rec->flags &= ~R_KILLPAT;
rec->flags |= R_SELECTED;
++NumSelected;
++NumEntries;
if (strlen(rec->name) >= MaxNameLen)
MaxNameLen = strlen(rec->name)+1;
}
}
redisplay(0);
}
cleanup()
{
RECORD *rec, *nrec;
for (rec = Rbase; rec; rec = nrec) {
nrec = rec->next;
if (rec->flags & R_KILLPAT) {
if (rec == DisplayTop)
DisplayTop = nrec;
rmrecord(rec);
}
}
}
rmrecord(rec)
RECORD *rec;
{
if (rec->flags & R_SOFTERR) {
puts("panic: soft error");
exit(1);
}
if (rec->prev)
rec->prev->next = rec->next;
else
Rbase = rec->next;
if (rec->next)
rec->next->prev = rec->prev;
rec->flags |= R_SOFTERR;
freestr(rec->name);
freestr(rec->comment);
freerecord(rec);
}
/*
* modify the comment field for the highlighted
* item.
*/
mod_comment(str)
char *str;
{
if (Highlighted) {
Modified = 1;
freestr(Highlighted->comment);
if (str[0]) {
Highlighted->comment = allocstr(str);
if (Highlighted->comment == NULL)
title("OUT OF MEMORY!");
} else {
Highlighted->comment = NULL;
}
redisplayone(Highlighted);
}
}
static RECORD *Cache;
resetsort()
{
cleanup();
Cache = Rbase;
}
void
addentry(name, comm, size)
char *name;
char *comm;
long size;
{
RECORD *rec;
short n;
Modified = 1;
rec = allocrecord();
if (rec == NULL) {
title("OUT OF MEMORY!");
return;
}
rec->name = allocstr(name);
if (rec->name == NULL) {
rmrecord(rec);
title("OUT OF MEMORY!");
return;
}
rec->comment = NULL;
if (strlen(comm)) {
rec->comment = allocstr(comm);
if (rec->comment == NULL) {
freestr(rec->name);
rmrecord(rec);
title("OUT OF MEMORY!");
return;
}
}
rec->bytes = size;
if (Rbase == NULL) {
Rbase = rec;
rec->prev = NULL;
rec->next = NULL;
} else {
short n = strcmp(name, Cache->name);
if (n == 0 && strcmp(name, KILLNAME) == 0)
n = 1;
if (n < 0) { /* name < Cache, move backwards */
while ((Cache = Cache->prev) && (n=strcmp(name, Cache->name)) < 0);
} else
if (n > 0) { /* name > Cache, move forwards */
while (Cache->next && (n=strcmp(name, Cache->next->name)) > 0)
Cache = Cache->next;
if (Cache->next && n == 0)
Cache = Cache->next;
}
if (Cache) {
rec->next = Cache->next; /* insert after cache */
rec->prev = Cache;
Cache->next = rec;
} else { /* or at beginning */
rec->next = Rbase;
rec->prev = NULL;
Rbase = rec;
}
if (rec->next)
rec->next->prev = rec;
if (n == 0) { /* replace if exact */
if (Cache->comment) {
char *swap = Cache->comment;
Cache->comment = rec->comment;
rec->comment = swap;
Cache->flags |= R_UPDATE;
}
}
}
rec->flags = R_SELECTED;
++NumSelected;
++NumEntries;
if (MaxNameLen <= strlen(rec->name))
MaxNameLen = strlen(rec->name) + 1;
Cache = rec;
}