home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CDPD Public Domain Collection for CDTV 3
/
CDPDIII.bin
/
pd
/
utilities
/
dirutils
/
visualshell
/
src
/
tree.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-29
|
15KB
|
516 lines
/*********************************
* *
* Visual Shell v1.17 10/92 *
* *
* by Torsten Jürgeleit *
* *
* tree part *
* *
*********************************/
/* Includes */
#include "includes.h"
#include "imports.h"
#include "protos.h"
/* Show directory tree */
VOID
action_tree(VOID)
{
struct FileRequest *freq = &file_req[active_freq];
struct TreeRequest *treq = &tree_req;
struct TreeNode *old_cursor_tnode = NULL;
BYTE *name = &file2_buffer[0];
SHORT error;
if ((error = build_device_name(name, freq->fr_DirLock)) ==
VSH_STATUS_NORMAL) {
hcomp_freq_cursor(freq);
print_info_line(INFO_LINE_MODE_EMPTY);
print_fkey_text(FKEY_MODE_NONE);
if ((error = build_dir_tree(treq, name)) == VSH_STATUS_NORMAL) {
/* Get our position in dir tree */
name = BaseName(&freq->fr_DirName[0]);
do {
old_cursor_tnode = get_tree_node_by_name(treq, old_cursor_tnode,
name);
} while (Strcmp(&freq->fr_DirName[0], build_tnode_path_name(treq,
old_cursor_tnode)));
treq->tr_DirNode = old_cursor_tnode;
treq->tr_CursorNode = &treq->tr_RootNode;
treq->tr_XPos = 0;
treq->tr_YPos = 0;
print_tree_page(treq);
do {
ULONG signals = Wait(SIGF_INTUITION | SIGF_ACTION);
if (signals & SIGF_INTUITION) { /* timing events from Intuition */
struct IntuiMessage *msg;
if (msg = (struct IntuiMessage *)
GetMsg(con_window->UserPort)) {
ULONG class = msg->Class;
ReplyMsg((struct Message *)msg);
switch (class) {
case REFRESHWINDOW :
print_tree_page(treq);
break;
case INTUITICKS :
if (auto_repeat) {
scroll_tree_req();
}
break;
}
}
}
if (signals & SIGF_ACTION) {
switch (action) {
case VSH_ACTION_NUM_ENTER :
error = read_new_dir(freq, build_tnode_path_name(treq,
treq->tr_CursorNode), READ_DIR_MODE_NO_OUTPUT);
break;
case VSH_ACTION_SPEED_SEARCH :
old_cursor_tnode = treq->tr_CursorNode;
if (get_input(INPUT_MODE_TREQ_ENTRY, &gadget_buffer[0])
== FALSE) {
move_treq_cursor(treq, old_cursor_tnode,
MOVE_MODE_NORMAL);
}
print_fkey_text(FKEY_MODE_QUIT_ONLY);
print_treq_status(treq);
break;
case VSH_ACTION_SCROLL_LEFT :
case VSH_ACTION_SCROLL_RIGHT :
case VSH_ACTION_SCROLL_UP :
case VSH_ACTION_SCROLL_DOWN :
scroll_tree_req();
break;
}
}
} while (action != VSH_ACTION_QUIT && action != VSH_ACTION_ESC &&
action != VSH_ACTION_NUM_ENTER);
}
print_status(VSH_STATUS_FREE_TREE);
free_dir_tree(treq);
status = error;
draw_requesters(DRAW_MODE_CLEAR);
}
}
/* Displaye tree page */
VOID
print_tree_page(struct TreeRequest *treq)
{
SetAPen(con_rport, (LONG)COLOR0);
RectFill(con_rport, (LONG)(BORDER_LEFT - 2), (LONG)
(BORDER_TOP_HIDDEN - 1), (LONG)(vsh_width - BORDER_RIGHT
+ 1), (LONG)(cli_vpos - 3));
draw_line(COLOR1, (USHORT)2, (USHORT)(BORDER_TOP_HIDDEN - 2),
(USHORT)(vsh_width - 3), (USHORT)(BORDER_TOP_HIDDEN - 2));
move_treq_cursor(treq, treq->tr_DirNode, MOVE_MODE_NO_CURSOR);
print_fkey_text(FKEY_MODE_QUIT_ONLY);
print_treq_status(treq);
}
/* Build directory tree */
SHORT
build_dir_tree(struct TreeRequest *treq, BYTE *dev_name)
{
struct TreeNode *tnode = &tree_req.tr_RootNode;
SHORT error;
strcpy(&treq->tr_DeviceName[0], dev_name);
strcpy(&treq->tr_DirName[0], dev_name);
NewList((struct List *)&tnode->tn_List); /* init root node */
tnode->tn_Node.mln_Succ = NULL;
tnode->tn_Node.mln_Pred = NULL;
tnode->tn_ParentNode = NULL; /* indicates root node */
tnode->tn_XPos = 0;
tnode->tn_YPos = 0;
tnode->tn_MaxDirs = 1;
strcpy(&tnode->tn_Name[0], dev_name);
enable_abort = 1;
do {
if ((error = read_tree_dirs(treq, tnode)) == VSH_STATUS_NORMAL) {
tnode = get_next_unscanned_tree_node(treq, tnode);
}
} while (tnode && error == VSH_STATUS_NORMAL);
enable_abort = 0;
return(error);
}
/* Get all subdirectories in given directory */
SHORT
read_tree_dirs(struct TreeRequest *treq, struct TreeNode *parent_tnode)
{
struct MinList *list = &parent_tnode->tn_List;
struct TreeNode *tnode;
BPTR lock;
BYTE *path = &path1_buffer[0];
BOOL keepon = TRUE;
SHORT error = VSH_STATUS_NORMAL;
if (!(lock = quiet_lock(&treq->tr_DirName[0], (LONG)SHARED_LOCK))) {
error = VSH_ERROR_LOCK_FAILED;
} else {
if (Examine(lock, fib) == DOSFALSE) { /* enter dir */
error = VSH_ERROR_EXAMINE_FAILED;
} else {
/* Scan loop */
do {
/* ESC pressed ? */
if (CheckAbort(NULL)) {
error = VSH_ERROR_ABORTED;
} else {
/* Get next dir entry */
if (ExNext(lock, fib) == DOSFALSE) {
if (IoErr() != ERROR_NO_MORE_ENTRIES) {
error = VSH_ERROR_EXNEXT_FAILED;
}
keepon = FALSE;
} else {
/* New dir found */
if (fib->fib_DirEntryType > 0) {
if (!(tnode = (struct TreeNode *)AllocMem((LONG)
sizeof(struct TreeNode), MEMF_PUBLIC |
MEMF_CLEAR))) {
error = VSH_ERROR_OUT_OF_MEM;
} else {
/* Build new directory tree node */
NewList((struct List *)&tnode->tn_List);
tnode->tn_XPos = parent_tnode->tn_XPos + 1;
tnode->tn_YPos = 0;
tnode->tn_MaxDirs = 1;
tnode->tn_MaxDepth = tnode->tn_XPos + 1;
tnode->tn_ParentNode = parent_tnode;
strcpy(&tnode->tn_Name[0], &fib->fib_FileName[0]);
AddTail((struct List *)list, (struct Node *)tnode);
/* Print full dir name in status line */
if ((error = build_path_name_from_lock(path, lock))
== VSH_STATUS_NORMAL) {
print_dos_status(DOS_MODE_TREE, path, NULL);
}
}
}
}
}
} while (error == VSH_STATUS_NORMAL && keepon == TRUE);
}
UnLock(lock);
}
return(error);
}
/* Get node of next unscanned directory in tree */
struct TreeNode *
get_next_unscanned_tree_node(struct TreeRequest *treq,
struct TreeNode *parent_tnode)
{
struct TreeNode *tnode;
ULONG max_dirs, max_depth;
BYTE *ptr, *path = &treq->tr_DirName[0];
BOOL keepon = TRUE;
tnode = (struct TreeNode *)parent_tnode->tn_List.mlh_Head; /* try to go deeper */
if (tnode->tn_Node.mln_Succ) { /* list not empty ? */
tnode->tn_YPos = parent_tnode->tn_YPos;
TackOn(path, &tnode->tn_Name[0]);
} else {
do { /* else go back */
ptr = BaseName(path); /* go one dir back */
if (*(ptr - 1) == '/') {
ptr--;
}
*ptr = '\0';
tnode = (struct TreeNode *)parent_tnode->tn_Node.mln_Succ; /* next dir in list */
if (tnode->tn_Node.mln_Succ) { /* not end of list ? */
tnode->tn_YPos = parent_tnode->tn_YPos + parent_tnode->tn_MaxDirs;
TackOn(path, &tnode->tn_Name[0]);
keepon = FALSE;
} else {
if (!(parent_tnode = parent_tnode->tn_ParentNode)) { /* root reached ? */
tnode = NULL;
keepon = FALSE;
} else {
max_dirs = 0; /* count dirs and get max depth in branch of tree */
max_depth = 0;
for (tnode = (struct TreeNode *)parent_tnode->tn_List.mlh_Head;
tnode->tn_Node.mln_Succ; tnode = (struct TreeNode *)
tnode->tn_Node.mln_Succ) {
max_dirs += tnode->tn_MaxDirs;
if (tnode->tn_MaxDepth > max_depth) {
max_depth = tnode->tn_MaxDepth;
}
}
parent_tnode->tn_MaxDirs += max_dirs - 1;
parent_tnode->tn_MaxDepth = max_depth;
}
}
} while (keepon == TRUE);
}
return(tnode);
}
/* Free directory tree */
VOID
free_dir_tree(struct TreeRequest *treq)
{
struct TreeNode *tnode = &treq->tr_RootNode;
struct MinList *list;
do {
list = &tnode->tn_List;
if ((struct MinList *)list->mlh_TailPred != list) { /* list not empty ? */
tnode = (struct TreeNode *)list->mlh_Head;
} else {
if (tnode = tnode->tn_ParentNode) {
FreeMem((APTR)RemHead((struct List *)&tnode->tn_List), (LONG)
sizeof(struct TreeNode));
}
}
} while (tnode);
}
/* Scroll directory tree */
VOID
scroll_tree_req(VOID)
{
struct TreeRequest *treq = &tree_req;
struct TreeNode *tnode2, *tnode = treq->tr_CursorNode;
USHORT columns = treq->tr_Columns, rows = treq->tr_Rows;
ULONG cxpos, cypos, xpos = treq->tr_XPos, ypos = treq->tr_YPos,
max_dirs = treq->tr_RootNode.tn_MaxDepth,
max_depth = treq->tr_RootNode.tn_MaxDirs;
do {
switch (scroll_flag) {
case 1 : /* scroll up */
tnode = get_prev_column_tree_node(tnode);
break;
case 2 : /* scroll down */
tnode = get_next_column_tree_node(tnode);
break;
case 4 : /* scroll left */
if (tnode2 = tnode->tn_ParentNode) {
tnode = tnode2;
}
break;
case 8 : /* scroll right */
tnode2 = (struct TreeNode *)tnode->tn_List.mlh_Head;
if (tnode2->tn_Node.mln_Succ) {
tnode = tnode2;
} else {
tnode = get_next_column_tree_node(tnode);
}
break;
}
if (tnode != treq->tr_CursorNode) {
cxpos = tnode->tn_XPos;
cypos = tnode->tn_YPos;
if (cxpos <= xpos) {
xpos = cxpos;
if (xpos) {
xpos--;
}
} else {
if (cxpos >= (xpos + columns - 1)) {
xpos = cxpos - columns + 1;
if ((xpos + columns) < max_dirs) {
xpos++;
}
}
}
if (cypos <= ypos) {
ypos = cypos;
if (ypos) {
ypos--;
}
} else {
if (cypos >= (ypos + rows - 1)) {
ypos = cypos - rows + 1;
if ((ypos + rows) < max_depth) {
ypos++;
}
}
}
hcomp_treq_cursor(treq);
treq->tr_CursorNode = tnode;
if (xpos != treq->tr_XPos || ypos != treq->tr_YPos) {
treq->tr_XPos = xpos;
treq->tr_YPos = ypos;
print_dir_tree(treq);
}
hcomp_treq_cursor(treq);
print_treq_status(treq);
}
} while (vsh_scroll_speed == SCROLL_SPEED_FAST && auto_repeat);
}
/* Build full path name for given node in dir tree */
BYTE *
build_tnode_path_name(struct TreeRequest *treq,
struct TreeNode *search_tnode)
{
struct TreeNode *tnode2, *tnode = &treq->tr_RootNode;
ULONG xpos = search_tnode->tn_XPos, ypos = search_tnode->tn_YPos;
BYTE *path = &path1_buffer[0];
strcpy(path, &tnode->tn_Name[0]);
while (tnode != search_tnode) {
tnode2 = (struct TreeNode *)tnode->tn_Node.mln_Succ;
if (tnode2 && tnode2->tn_Node.mln_Succ && tnode2->tn_YPos <= ypos) {
tnode = tnode2; /* next entry in list */
tnode2 = (struct TreeNode *)tnode->tn_Node.mln_Succ;
if (!tnode2->tn_Node.mln_Succ || tnode2->tn_YPos > ypos) {
TackOn(path, &tnode->tn_Name[0]);
}
} else {
tnode2 = (struct TreeNode *)tnode->tn_List.mlh_Head;
if (tnode2->tn_Node.mln_Succ && tnode2->tn_XPos <= xpos) {
tnode = tnode2; /* go deeper */
tnode2 = (struct TreeNode *)tnode->tn_Node.mln_Succ;
if (!tnode2->tn_Node.mln_Succ || tnode2->tn_YPos > ypos) {
TackOn(path, &tnode->tn_Name[0]);
}
}
}
}
return(path);
}
/* Jump to an specified entry in dir tree */
VOID
jump_to_treq_entry(BYTE *name, USHORT mode)
{
struct TreeRequest *treq = &tree_req;
struct TreeNode *tnode;
if (mode == JUMP_MODE_FIRST) {
tnode = NULL;
} else {
tnode = treq->tr_CursorNode;
}
if ((tnode = get_tree_node_by_name(treq, tnode, name)) || (tnode =
get_tree_node_by_name(treq, (struct TreeNode *)NULL, name))) {
move_treq_cursor(treq, tnode, MOVE_MODE_NORMAL);
}
}
/* Move cursor to specified entry in dir tree */
VOID
move_treq_cursor(struct TreeRequest *treq, struct TreeNode *tnode,
USHORT mode)
{
ULONG xpos = treq->tr_XPos, ypos = treq->tr_YPos,
cxpos = tnode->tn_XPos, cypos = tnode->tn_YPos;
USHORT columns = treq->tr_Columns, rows = treq->tr_Rows,
max_depth = treq->tr_RootNode.tn_MaxDepth,
max_dirs = treq->tr_RootNode.tn_MaxDirs;
if (tnode != treq->tr_CursorNode || mode == MOVE_MODE_NO_CURSOR) {
if (mode != MOVE_MODE_NO_CURSOR) {
hcomp_treq_cursor(treq);
}
if (cxpos <= xpos || cxpos >= (xpos + columns - 1) || cypos <= ypos ||
cypos >= (ypos + rows - 1)) {
if (max_depth > columns) {
if (cxpos <= (columns / 2)) {
xpos = 0;
} else {
xpos = cxpos - columns / 2;
if ((xpos + columns) > max_depth) {
xpos -= (xpos + columns) - max_depth;
}
}
}
if (max_dirs > rows) {
if (cypos <= (rows / 2)) {
ypos = 0;
} else {
ypos = cypos - rows / 2;
if ((ypos + rows) > max_dirs) {
ypos -= (ypos + rows) - max_dirs;
}
}
}
treq->tr_XPos = xpos;
treq->tr_YPos = ypos;
print_dir_tree(treq);
} else {
if (mode == MOVE_MODE_NO_CURSOR) {
print_dir_tree(treq);
}
}
treq->tr_CursorNode = tnode;
hcomp_treq_cursor(treq);
}
}
/* Get tree node by given name */
struct TreeNode *
get_tree_node_by_name(struct TreeRequest *treq, struct TreeNode *tnode,
BYTE *name)
{
struct TreeNode *tnode2;
ULONG len = strlen(name);
BYTE *ptr, *path = &treq->tr_DirName[0];
BOOL keepon, searching = TRUE;
if (! len) {
tnode = &treq->tr_RootNode;
strcpy(path, &tnode->tn_Name[0]);
} else {
if (! tnode) {
tnode = &treq->tr_RootNode;
strcpy(path, &tnode->tn_Name[0]);
if (! Strncmp(&tnode->tn_Name[0], name, len)) {
searching = FALSE; /* found */
}
}
while (searching == TRUE) {
tnode2 = (struct TreeNode *)tnode->tn_List.mlh_Head; /* try to go deeper */
if (tnode2->tn_Node.mln_Succ) { /* list not empty ? */
tnode = tnode2;
TackOn(path, &tnode->tn_Name[0]);
} else {
keepon = TRUE;
do { /* else go back */
ptr = BaseName(path); /* go one dir back */
if (*(ptr - 1) == (BYTE)'/') {
ptr--;
}
*ptr = '\0';
tnode2 = (struct TreeNode *)tnode->tn_Node.mln_Succ; /* next dir in list */
if (tnode2->tn_Node.mln_Succ) { /* not end of list ? */
tnode = tnode2;
TackOn(path, &tnode->tn_Name[0]);
keepon = FALSE;
} else {
if (!(tnode = tnode->tn_ParentNode)) { /* root reached ? */
tnode = NULL;
keepon = FALSE;
searching = FALSE; /* not found */
}
}
} while (keepon == TRUE);
}
if (searching == TRUE) {
if (! Strncmp(&tnode->tn_Name[0], name, len)) {
searching = FALSE;
}
}
}
}
return(tnode);
}