home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CDPD Public Domain Collection for CDTV 3
/
CDPDIII.bin
/
pd
/
utilities
/
dirutils
/
visualshell
/
src
/
subs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-28
|
33KB
|
1,101 lines
/*********************************
* *
* Visual Shell v1.17 10/92 *
* *
* by Torsten Jürgeleit *
* *
* subroutine part *
* *
*********************************/
/* Includes */
#include "includes.h"
#include "imports.h"
#include "protos.h"
/* Lock given name with disabled system requesters */
BPTR
quiet_lock(BYTE *name, LONG mode)
{
BPTR lock;
APTR old_window, *ptr = &((struct Process *)main_task)->pr_WindowPtr;
old_window = *ptr;
*ptr = (APTR)-1L;
lock = Lock(name, mode);
*ptr = old_window;
return(lock);
}
/* Examine given lock with disabled system requesters */
SHORT
quiet_examine(BPTR lock, struct FileInfoBlock *fib)
{
APTR old_window, *ptr = &((struct Process *)main_task)->pr_WindowPtr;
SHORT error;
old_window = *ptr;
*ptr = (APTR)-1L;
if (Examine(lock, fib) == DOSFALSE) {
error = VSH_ERROR_EXAMINE_FAILED;
} else {
error = VSH_STATUS_NORMAL;
}
*ptr = old_window;
return(error);
}
/* Check given path name for directory */
SHORT
check_for_dir(BYTE *dir_name)
{
BPTR lock;
SHORT error;
if (!(lock = quiet_lock(dir_name, (LONG)SHARED_LOCK))) {
error = VSH_ERROR_DIR_NOT_FOUND;
} else {
if (Examine(lock, fib) == DOSFALSE) {
error = VSH_ERROR_EXAMINE_FAILED;
} else {
if (fib->fib_DirEntryType < 0) {
error = VSH_ERROR_NO_DIR;
} else {
error = VSH_STATUS_NORMAL;
}
}
UnLock(lock);
}
return(error);
}
/* Check a file for a load file */
SHORT
check_for_load_file(BYTE *file_name)
{
BPTR lock, fh;
ULONG data;
SHORT error = VSH_STATUS_NORMAL;
if (!(lock = quiet_lock(file_name, (LONG)SHARED_LOCK))) {
error = VSH_ERROR_LOCK_FAILED;
} else {
if (Examine(lock, fib) == DOSFALSE) {
error = VSH_ERROR_EXAMINE_FAILED;
} else {
/* Check execute protection */
if (fib->fib_Protection & FIBF_EXECUTE) {
error = VSH_ERROR_EXECUTE_PROTECTED;
} else {
/* Open file and read first long word */
if (!(fh = Open(file_name, (LONG)MODE_OLDFILE))) {
error = VSH_ERROR_OPEN_FAILED;
} else {
if (Read(fh, (BYTE *)&data, 4L) != 4) {
error = VSH_ERROR_READ_FAILED;
} else {
/* Check for file header hunk */
if (data != 0x03f3) {
error = VSH_ERROR_NO_LOAD_FILE;
}
}
Close(fh);
}
}
}
UnLock(lock);
}
return(get_dos_error(error));
}
/* Read new directory for specified filerequester */
SHORT
read_new_dir(struct FileRequest *freq, BYTE *dir_name, USHORT mode)
{
SHORT error;
print_status(VSH_STATUS_READ_DIR);
if (mode != READ_DIR_MODE_NO_OUTPUT) {
hcomp_freq_cursor(freq);
print_info_line(INFO_LINE_MODE_EMPTY);
print_fkey_text(FKEY_MODE_NONE);
}
if (! dir_name) {
dir_name = &freq->fr_DirName[0];
}
if ((error = new_dir(freq, dir_name)) == VSH_STATUS_NORMAL) {
if ((error = read_dir(freq)) == VSH_STATUS_NORMAL) {
if ((error = get_dir_info(freq)) == VSH_STATUS_NORMAL && freq ==
&file_req[active_freq]) { /* active file req ? */
if (mode != READ_DIR_MODE_NO_CD) {
error = change_current_dir();
}
}
}
}
print_dir_name(freq, NULL);
refresh_dir_info(freq);
if (mode == READ_DIR_MODE_NORMAL || mode == READ_DIR_MODE_NO_CD ||
(mode == READ_DIR_MODE_NO_PRINT && error != VSH_STATUS_NORMAL)) {
print_freq_lines(freq, freq->fr_Display.d_FirstVisibleNode, (USHORT)0,
freq->fr_Display.d_VisibleLines);
hcomp_freq_cursor(freq);
print_info_line(INFO_LINE_MODE_NORMAL);
change_fkey_text();
}
return(error);
}
/* Read the same directory once again */
SHORT
read_same_dir(struct FileRequest *freq, USHORT mode)
{
struct FileNode *fnode;
struct MinList *old_file_list;
ULONG old_marked_entries, old_node_pos;
BYTE *old_node_name = &file1_buffer[0];
SHORT old_cursor_line, error = VSH_STATUS_NORMAL;
if (freq->fr_DirName[0] != '\0') { /* dir name != "" ? */
old_marked_entries = freq->fr_MarkedEntries;
old_file_list = freq->fr_Display.d_List;
freq->fr_Display.d_List = NULL;
if (mode != READ_SAME_DIR_MODE_NO_CURSOR) {
if ((old_cursor_line = freq->fr_CursorLine) != -1) {
fnode = get_file_node_under_cursor(freq);
old_node_pos = fnode->fn_Pos;
strncpy(old_node_name, &fnode->fn_Text[0], (size_t)
fnode->fn_NameLen);
*(old_node_name + fnode->fn_NameLen) = '\0';
}
}
if ((error = read_new_dir(freq, NULL, (mode ==
READ_SAME_DIR_MODE_NORMAL ? READ_DIR_MODE_NO_PRINT :
READ_DIR_MODE_NO_OUTPUT))) == VSH_STATUS_NORMAL) {
duplicate_marks(freq, old_file_list, old_marked_entries);
if (mode != READ_SAME_DIR_MODE_NO_CURSOR) {
duplicate_cursor_line(freq, old_node_name, old_node_pos,
old_cursor_line);
}
free_list(old_file_list, (ULONG)sizeof(struct FileNode));
print_freq_lines(freq, freq->fr_Display.d_FirstVisibleNode,
(USHORT)0, freq->fr_Display.d_VisibleLines);
if (mode == READ_SAME_DIR_MODE_NORMAL) {
hcomp_freq_cursor(freq);
print_info_line(INFO_LINE_MODE_NORMAL);
change_fkey_text();
}
}
}
return(error);
}
/* Enter new directory */
SHORT
new_dir(struct FileRequest *freq, BYTE *dir_name)
{
struct MinList *file_list;
BPTR dir_lock;
SHORT error;
if (!(dir_lock = quiet_lock(dir_name, (LONG)SHARED_LOCK))) {
error = VSH_ERROR_DIR_NOT_FOUND;
} else {
dir_name = &path1_buffer[0];
if ((error = build_path_name_from_lock(dir_name, dir_lock)) ==
VSH_STATUS_NORMAL) {
if (Examine(dir_lock, fib) == DOSFALSE) {
error = VSH_ERROR_EXAMINE_FAILED;
} else {
if (fib->fib_DirEntryType < 0) {
error = VSH_ERROR_NO_DIR;
} else {
if (!(file_list = (struct MinList *)AllocMem((LONG)
sizeof(struct MinList), MEMF_PUBLIC | MEMF_CLEAR))) {
error = VSH_ERROR_OUT_OF_MEM;
} else {
NewList((struct List *)file_list);
free_dir(freq);
strcpy(&freq->fr_DirName[0], dir_name);
freq->fr_Display.d_List = file_list;
freq->fr_DirLock = dir_lock;
CopyMem((BYTE *)&fib->fib_Date, (BYTE *)
&freq->fr_Info.i_LastChanged, (LONG)
sizeof(struct DateStamp));
return(VSH_STATUS_NORMAL);
}
}
}
}
UnLock(dir_lock);
}
return(error);
}
/* Build file list for specified filerequester */
SHORT
read_dir(struct FileRequest *freq)
{
struct AnchorPath *ap = &freq->fr_AnchorPath;
struct FileInfoBlock *info = &ap->ap_Info;
struct MinList *list = freq->fr_Display.d_List;
struct FileNode *fnode;
BPTR cd_lock;
LONG rc;
SHORT error = VSH_STATUS_NORMAL;
cd_lock = CurrentDir(freq->fr_DirLock);
if (!(rc = FindFirst(&freq->fr_FilePattern[0], ap))) {
do {
if (!(fnode = build_file_node(info))) {
error = VSH_ERROR_OUT_OF_MEM;
} else {
insert_file_node(fnode, list);
}
} while (error == VSH_STATUS_NORMAL && !(rc = FindNext(ap)));
}
FreeAnchorChain(ap);
CurrentDir(cd_lock);
if (error == VSH_STATUS_NORMAL) {
if (rc != ERROR_NO_MORE_ENTRIES) {
error = VSH_ERROR_FINDFIRST_OR_FINDNEXT_FAILED;
} else {
if (freq->fr_Display.d_NumEntries = count_file_nodes(list)) {
freq->fr_Display.d_FirstVisibleNode = list->mlh_Head;
freq->fr_CursorLine = 0;
}
}
}
return(error);
}
/* Get infos about directory */
SHORT
get_dir_info(struct FileRequest *freq)
{
struct Info *info = &freq->fr_Info;
SHORT error = VSH_STATUS_NORMAL;
if (Info(freq->fr_DirLock, idata) == DOSFALSE) {
error = VSH_ERROR_INFO_FAILED;
} else {
info->i_Valid = 1; /* mark info data as valid */
info->i_NumSoftErrors = idata->id_NumSoftErrors;
info->i_DiskState = idata->id_DiskState;
info->i_BytesPerBlock = idata->id_BytesPerBlock;
info->i_TotalSize = idata->id_NumBlocks * idata->id_BytesPerBlock;
info->i_FreeSize = info->i_TotalSize - idata->id_NumBlocksUsed
* idata->id_BytesPerBlock;
BtoCStr(&info->i_VolumeName[0], ((struct DosList *)
BTOC(idata->id_VolumeNode))->dol_Name, (LONG)MAX_FILE_NAME_LEN);
sum_file_sizes(freq);
}
return(error);
}
/* Free file list for specified filerequester */
VOID
free_dir(struct FileRequest *freq)
{
if (freq->fr_DirLock) {
UnLock(freq->fr_DirLock);
freq->fr_DirLock = NULL;
}
free_list(freq->fr_Display.d_List, (LONG)sizeof(struct FileNode));
freq->fr_Display.d_List = NULL;
free_list(freq->fr_SaveFileList, (LONG)sizeof(struct FileNode));
freq->fr_SaveFileList = NULL;
freq->fr_DirName[0] = '\0';
freq->fr_Info.i_Valid = 0; /* mark info data as invalid */
freq->fr_Display.d_NumEntries = 0;
freq->fr_SaveNumEntries = 0;
freq->fr_Display.d_FirstVisibleNode = NULL;
freq->fr_SaveFirstVisibleNode = NULL;
freq->fr_CursorLine = -1;
freq->fr_SaveCursorLine = -1;
freq->fr_MarkedEntries = 0;
freq->fr_SaveMarkedEntries = 0;
freq->fr_MarkedSize = 0;
freq->fr_SaveMarkedSize = 0;
freq->fr_Mode = FREQ_MODE_NORMAL;
}
/* Free the complete list and the list header */
VOID
free_list(struct MinList *list, ULONG size)
{
struct Node *node;
BOOL path_flag = FALSE;
if (list && size) {
if (size == sizeof(struct FileNode)) {
path_flag = TRUE; /* free path buffer - allocated by Find */
}
while (node = RemHead((struct List *)list)) {
if (path_flag == TRUE) {
DosFreeMem(((struct FileNode *)node)->fn_Path);
}
FreeMem(node, size);
}
FreeMem(list, (LONG)sizeof(struct MinList));
}
}
/* Build full path name from given lock */
SHORT
build_path_name_from_lock(BYTE *buffer, BPTR lock)
{
BYTE temp[MAX_PATH_NAME_LEN + 1];
SHORT error;
if (!PathName(lock, &temp[0], (LONG)MAX_PATH_NAME_LEN / FSIZE)) {
error = VSH_ERROR_NO_PATH_NAME;
} else {
if ((error = build_device_name(buffer, lock)) == VSH_STATUS_NORMAL) {
strcat(buffer, strchr(&temp[0], (USHORT)':') + 1);
}
}
return(error);
}
/* Build full path name from given file node */
VOID
build_path_name_from_file_node(BYTE *buffer, struct FileRequest *freq,
struct FileNode *fnode)
{
if (freq->fr_Mode == FREQ_MODE_FIND) {
strcpy(buffer, fnode->fn_Path);
} else {
strcpy(buffer, &freq->fr_DirName[0]);
}
append_base_name(buffer, fnode);
}
/* Build full path name from path relative to current directory */
SHORT
build_path_name_from_relative_path(BYTE *buffer, BYTE *path)
{
BPTR lock;
SHORT error;
if (!(lock = quiet_lock(path, (LONG)SHARED_LOCK))) {
error = VSH_ERROR_LOCK_FAILED;
} else {
error = build_path_name_from_lock(buffer, lock);
UnLock(lock);
}
return(error);
}
/* Append full path of specified entry at given pointer */
BYTE *
append_path_name(BYTE *buffer, struct FileRequest *freq,
struct FileNode *fnode, USHORT mode)
{
BPTR lock;
BYTE *ptr;
if (mode == APPEND_MODE_QUOTED) {
*buffer++ = '"';
}
if (freq->fr_Mode == FREQ_MODE_FIND) {
strcpy(buffer, fnode->fn_Path);
} else {
strcpy(buffer, &freq->fr_DirName[0]);
}
ptr = append_base_name(buffer, fnode);
if (!(lock = quiet_lock(buffer, (LONG)SHARED_LOCK))) {
ptr = NULL;
} else {
if (mode == APPEND_MODE_QUOTED) {
*ptr++ = '"';
*ptr = '\0';
}
UnLock(lock);
}
return(ptr);
}
/* Append base name of specified entry at given pointer */
BYTE *
append_base_name(BYTE *buffer, struct FileNode *fnode)
{
BYTE c;
buffer += strlen(buffer);
c = *(buffer - 1);
if (c != ':' && c != '/') {
*buffer++ = '/';
}
strncpy(buffer, &fnode->fn_Text[0], (size_t)fnode->fn_NameLen);
*(buffer += fnode->fn_NameLen) = '\0';
return(buffer);
}
/* Build device name for given lock */
SHORT
build_device_name(BYTE *buffer, BPTR lock)
{
struct DevInfo *dvi;
struct Task *task;
SHORT error = VSH_ERROR_NO_PATH_NAME;
/* First get ptr to file system task the lock belongs to */
if (!lock) { /* ZERO lock -> boot device */
task = (struct Task *)_parent_proc->pr_FileSystemTask;
} else {
task = (struct Task *)((struct FileLock *)BTOC(lock))->fl_Task;
}
/* Search device with this file system task in AmigaDOS device list */
Forbid();
for (dvi = (struct DevInfo *)GetDevInfo(NULL); dvi;
dvi = BTOC(dvi->dvi_Next)) {
if (dvi->dvi_Type == DLT_DEVICE && (struct Task *)dvi->dvi_Task ==
task && dvi->dvi_Name) {
/* Convert device name to C string and append ':' */
BtoCStr(buffer, dvi->dvi_Name, (LONG)MAX_FILE_NAME_LEN);
buffer += strlen(buffer);
*buffer++ = ':';
*buffer = '\0';
error = VSH_STATUS_NORMAL;
break;
}
}
Permit();
return(error);
}
/* Build device list for specified filerequester */
SHORT
read_devs(struct FileRequest *freq)
{
struct DevInfo *dvi = NULL;
struct MinList *list;
struct FileNode *fnode;
BPTR lock;
BYTE *path = &path2_buffer[0];
BOOL ram_flag = FALSE;
SHORT error = VSH_STATUS_NORMAL;
print_status(VSH_STATUS_READ_DEVS);
print_fkey_text(FKEY_MODE_NONE);
freq->fr_Display.d_List = NULL;
freq->fr_Display.d_NumEntries = 0;
freq->fr_Display.d_FirstVisibleNode = NULL;
freq->fr_CursorLine = -1;
freq->fr_Mode = FREQ_MODE_DEVS_ASN;
if (!(list = (struct MinList *)AllocMem((LONG)
sizeof(struct MinList), MEMF_PUBLIC | MEMF_CLEAR))) {
error = VSH_ERROR_OUT_OF_MEM;
} else {
NewList((struct List *)list);
freq->fr_Display.d_List = list;
while (dvi = (struct DevInfo *)GetDevInfo((struct DeviceList *)dvi)) {
switch (dvi->dvi_Type) {
case DLT_DEVICE :
if (dvi->dvi_Task && dvi->dvi_Name) {
if (!(fnode = build_dev_node(dvi))) {
return(VSH_ERROR_OUT_OF_MEM);
} else {
if (! strncmp(&fnode->fn_Text[0], "RAM:", 4L)) {
ram_flag = TRUE;
}
insert_file_node(fnode, list);
}
}
break;
case DLT_VOLUME :
if (dvi->dvi_Task && dvi->dvi_Name) {
if (!(fnode = build_dev_node(dvi))) {
return(VSH_ERROR_OUT_OF_MEM);
} else {
insert_file_node(fnode, list);
}
}
break;
case DLT_DIRECTORY :
BtoCStr(path, dvi->dvi_Name, (LONG)MAX_PATH_NAME_LEN);
strcat(path, (BYTE *)":");
if (lock = quiet_lock(path, (LONG)SHARED_LOCK)) {
if (Examine(lock, fib) == DOSTRUE) {
if (fib->fib_DirEntryType > 0) { /* dir ? */
if (!(fnode = build_dev_node(dvi))) {
UnLock(lock);
return(VSH_ERROR_OUT_OF_MEM);
} else {
insert_file_node(fnode, list);
}
}
}
UnLock(lock);
}
break;
}
}
if (ram_flag == FALSE) {
if (!(fnode = build_dev_node(NULL))) {
return(VSH_ERROR_OUT_OF_MEM);
} else {
insert_file_node(fnode, list);
}
}
if (freq->fr_Display.d_NumEntries = count_file_nodes(list)) {
freq->fr_Display.d_FirstVisibleNode = list->mlh_Head;
freq->fr_CursorLine = 0;
}
}
return(error);
}
/* Get file node under cursor of specified filerequester */
struct FileNode *
get_file_node_under_cursor(struct FileRequest *freq)
{
struct FileNode *fnode = NULL;
SHORT i, cursor_line = freq->fr_CursorLine;
if (cursor_line != -1) {
fnode = (struct FileNode *)freq->fr_Display.d_FirstVisibleNode;
for (i = cursor_line; i; i--) {
fnode = (struct FileNode *)fnode->fn_Node.mln_Succ;
}
}
return(fnode);
}
/* Remove file node from file list of specified filerequester */
struct FileNode *
remove_file_node(struct FileRequest *freq, struct FileNode *fnode)
{
struct FileNode *next_fnode;
struct MinNode *fv_node = freq->fr_Display.d_FirstVisibleNode;
USHORT vlines = freq->fr_Display.d_VisibleLines;
ULONG num_entries = freq->fr_Display.d_NumEntries,
fv_pos = ((struct FileNode *)fv_node)->fn_Pos, pos = fnode->fn_Pos;
if (pos == fv_pos) { /* change first visible node */
if (pos > 1 && (num_entries - pos) < vlines) {
fv_node = fv_node->mln_Pred;
} else {
fv_node = fv_node->mln_Succ;
}
} else {
if (num_entries > vlines && pos > fv_pos && fv_pos == (num_entries -
vlines + 1)) {
fv_node = fv_node->mln_Pred;
}
}
freq->fr_Display.d_FirstVisibleNode = fv_node;
freq->fr_Display.d_NumEntries = recount_file_nodes(fnode);
if (fnode->fn_Type == ENTRY_TYPE_DIR) { /* dir ? */
freq->fr_Info.i_Dirs--;
} else {
freq->fr_Info.i_FileSizes -= fnode->fn_Size;
freq->fr_Info.i_Files--;
}
next_fnode = (struct FileNode *)fnode->fn_Node.mln_Succ;
Remove((struct Node *)fnode);
FreeMem(fnode, (LONG)sizeof(struct FileNode));
print_freq_lines(freq, fv_node, (USHORT)0, vlines);
refresh_dir_info(freq);
return(next_fnode);
}
/* Rename file node from file list of specified filerequester */
VOID
rename_file_node(struct FileRequest *freq, struct FileNode *fnode,
BYTE *name)
{
struct MinList *flist = freq->fr_Display.d_List;
struct MinNode *fv_node = freq->fr_Display.d_FirstVisibleNode;
BYTE c, *ptr = &fnode->fn_Text[0];
USHORT i, vlines = freq->fr_Display.d_VisibleLines;
ULONG num_entries = freq->fr_Display.d_NumEntries,
fv_pos = ((struct FileNode *)fv_node)->fn_Pos,
old_pos = fnode->fn_Pos, new_pos;
Remove((struct Node *)fnode);
for (i = 0; i < MAX_FILE_NAME_LEN; i++) { /* insert new fnode name */
if (!(c = *name++)) {
break;
} else {
*ptr++ = c;
}
}
fnode->fn_NameLen = i;
for ( ; i < MAX_FILE_NAME_LEN; i++) { /* clear rest of file name */
*ptr++ = ' ';
}
insert_file_node(fnode, flist);
if ((new_pos = fnode->fn_Pos) != old_pos) { /* position changed ? */
if (old_pos == fv_pos) { /* change first visible node */
if (old_pos > 1 && (num_entries - old_pos) < vlines) {
fv_pos = old_pos - 1;
} else {
fv_pos = old_pos + 1;
}
fv_node = get_list_node(flist, num_entries, fv_pos);
} else {
fv_pos = ((struct FileNode *)fv_node)->fn_Pos;
if (new_pos < fv_pos && (num_entries - fv_pos) < vlines) {
fv_node = fv_node->mln_Pred;
}
}
}
freq->fr_Display.d_FirstVisibleNode = fv_node;
freq->fr_Display.d_NumEntries = count_file_nodes(flist);
print_freq_lines(freq, fv_node, (USHORT)0, vlines);
}
/* Duplicate file list from one filerequester to another one */
SHORT
duplicate_file_list(struct FileRequest *freq1, struct FileRequest *freq2)
{
struct FileNode *fnode1, *fnode2;
struct MinList *flist1, *flist2;
BPTR dir_lock;
ULONG num_entries, marked_entries, marked_size;
SHORT error = VSH_STATUS_NORMAL;
if (!(dir_lock = DupLock(freq1->fr_DirLock))) {
error = VSH_ERROR_OUT_OF_MEM;
} else {
if (!(flist2 = (struct MinList *)AllocMem((LONG)
sizeof(struct MinList), MEMF_PUBLIC))) {
error = VSH_ERROR_OUT_OF_MEM;
} else {
NewList((struct List *)flist2);
if (freq1->fr_Mode == FREQ_MODE_DEVS_ASN || freq1->fr_Mode ==
FREQ_MODE_FIND) {
flist1 = freq1->fr_SaveFileList;
num_entries = freq1->fr_SaveNumEntries;
marked_entries = freq1->fr_SaveMarkedEntries;
marked_size = freq1->fr_SaveMarkedSize;
} else {
flist1 = freq1->fr_Display.d_List;
num_entries = freq1->fr_Display.d_NumEntries;
marked_entries = freq1->fr_MarkedEntries;
marked_size = freq1->fr_MarkedSize;
}
fnode1 = (struct FileNode *)flist1->mlh_Head;
while (fnode1->fn_Node.mln_Succ && error == VSH_STATUS_NORMAL) {
if (!(fnode2 = (struct FileNode *)AllocMem((LONG)
sizeof(struct FileNode), MEMF_PUBLIC | MEMF_CLEAR))) {
error = VSH_ERROR_OUT_OF_MEM;
} else {
strcpy(&fnode2->fn_Text[0], &fnode1->fn_Text[0]); /* copy file node */
CopyMem((BYTE *)fnode1, (BYTE *)fnode2, (LONG)
sizeof(struct FileNode));
AddTail((struct List *)flist2, (struct Node *)fnode2);
fnode1 = (struct FileNode *)fnode1->fn_Node.mln_Succ;
}
}
if (error == VSH_STATUS_NORMAL) {
free_dir(freq2);
strcpy(&freq2->fr_DirName[0], &freq1->fr_DirName[0]);
freq2->fr_DirLock = dir_lock;
freq2->fr_Display.d_List = flist2;
freq2->fr_Display.d_NumEntries = num_entries;
freq2->fr_Display.d_FirstVisibleNode = flist2->mlh_Head;
if (num_entries) {
freq2->fr_CursorLine = 0;
} else {
freq2->fr_CursorLine = -1;
}
freq2->fr_MarkedEntries = marked_entries;
freq2->fr_MarkedSize = marked_size;
CopyMem((BYTE *)&freq1->fr_Info, (BYTE *)&freq2->fr_Info,
(LONG)sizeof(struct Info));
return(VSH_STATUS_NORMAL);
}
free_list(flist2, (LONG)sizeof(struct FileNode));
FreeMem(flist2, (LONG)sizeof(struct MinList));
}
UnLock(dir_lock);
}
return(error);
}
/* Duplicate marks from one file list to another */
VOID
duplicate_marks(struct FileRequest *freq, struct MinList *old_file_list,
ULONG old_marked_entries)
{
struct FileNode *fnode, *old_fnode = (struct FileNode *)
old_file_list->mlh_Head,
*new_fnode = (struct FileNode *)
freq->fr_Display.d_List->mlh_Head;
if (old_marked_entries) {
while (old_fnode->fn_Node.mln_Succ) {
if (old_fnode->fn_Marked) {
if (fnode = search_file_node(new_fnode, &old_fnode->fn_Text[0],
old_fnode->fn_NameLen)) {
fnode->fn_Marked = 1;
freq->fr_MarkedSize += fnode->fn_Size;
freq->fr_MarkedEntries++;
new_fnode = fnode;
}
}
old_fnode = (struct FileNode *)old_fnode->fn_Node.mln_Succ;
}
}
}
/* Duplicate cursor position from one filerequester to another */
VOID
duplicate_cursor_line(struct FileRequest *freq, BYTE *old_name,
ULONG old_pos, SHORT old_cursor_line)
{
struct FileNode *fnode;
if (old_cursor_line != -1) {
if (!(fnode = search_file_node((struct FileNode *)
freq->fr_Display.d_List->mlh_Head, old_name, (USHORT)
strlen(old_name)))) {
fnode = (struct FileNode *)get_list_node(freq->fr_Display.d_List,
freq->fr_Display.d_NumEntries, old_pos);
}
move_freq_cursor(freq, fnode, MOVE_MODE_NO_OUTPUT);
}
}
/* Restore old cursor position for given filerequester */
VOID
restore_old_cursor_line(struct FileRequest *freq, BYTE *old_name,
ULONG old_pos, SHORT old_cursor_line)
{
struct FileNode *fnode;
if (old_cursor_line == -1 || !freq->fr_Display.d_NumEntries) {
freq->fr_CursorLine = -1;
print_info_line(INFO_LINE_MODE_EMPTY);
} else {
if (!(fnode = search_file_node((struct FileNode *)
freq->fr_Display.d_List->mlh_Head, old_name, (USHORT)
strlen(old_name)))) {
fnode = (struct FileNode *)get_list_node(freq->fr_Display.d_List,
freq->fr_Display.d_NumEntries, old_pos);
}
move_freq_cursor(freq, fnode, MOVE_MODE_NO_HCOMP);
}
}
/* Jump to an specified entry in file requester */
VOID
jump_to_freq_entry(BYTE *name, USHORT mode)
{
struct FileRequest *freq = &file_req[active_freq];
struct FileNode *fnode;
if (mode == JUMP_MODE_FIRST) {
fnode = search_file_node((struct FileNode *)
freq->fr_Display.d_List->mlh_Head, name, (USHORT)0);
} else {
fnode = (struct FileNode *)
get_file_node_under_cursor(freq)->fn_Node.mln_Succ;
/* End of list ? */
if (fnode->fn_Node.mln_Succ) {
if (!(fnode = search_file_node(fnode, name, (USHORT)0))) {
fnode = search_file_node((struct FileNode *)
freq->fr_Display.d_List->mlh_Head, name, (USHORT)0);
}
} else {
fnode = search_file_node((struct FileNode *)
freq->fr_Display.d_List->mlh_Head, name, (USHORT)0);
}
}
move_freq_cursor(freq, fnode, MOVE_MODE_NORMAL);
}
/* Move cursor to specified entry in file requester */
VOID
move_freq_cursor(struct FileRequest *freq, struct FileNode *fnode,
USHORT mode)
{
ULONG cursor_line, num_entries = freq->fr_Display.d_NumEntries;
USHORT i, vlines = freq->fr_Display.d_VisibleLines,
vlines_half = vlines >> 1;
if (mode == MOVE_MODE_NORMAL) {
hcomp_freq_cursor(freq);
print_info_line(INFO_LINE_MODE_EMPTY);
}
if (fnode) {
cursor_line = fnode->fn_Pos - 1;
if (num_entries > vlines) {
if (cursor_line < vlines_half) {
fnode = (struct FileNode *)freq->fr_Display.d_List->mlh_Head;
} else {
if (cursor_line >= (num_entries - vlines_half)) {
fnode = (struct FileNode *)
freq->fr_Display.d_List->mlh_TailPred;
i = vlines - 1;
} else {
i = vlines_half - (!(vlines & 1) ? 1 : 0); /* dec for even num of visible lines */
}
for ( ; i; i--) {
fnode = (struct FileNode *)fnode->fn_Node.mln_Pred;
}
cursor_line -= fnode->fn_Pos - 1;
}
} else {
fnode = (struct FileNode *)freq->fr_Display.d_List->mlh_Head;
}
} else {
if (freq->fr_DirLock && freq->fr_Display.d_NumEntries) {
fnode = (struct FileNode *)freq->fr_Display.d_List->mlh_Head;
cursor_line = 0;
} else {
cursor_line = -1;
}
}
if (!fnode || fnode != (struct FileNode *)
freq->fr_Display.d_FirstVisibleNode) {
freq->fr_Display.d_FirstVisibleNode = (struct MinNode *)fnode;
if (mode != MOVE_MODE_NO_OUTPUT) {
print_freq_lines(freq, (struct MinNode *)fnode, (USHORT)0, vlines);
}
} else {
if (mode == MOVE_MODE_PRINT) {
print_freq_lines(freq, freq->fr_Display.d_FirstVisibleNode,
(USHORT)0, vlines);
}
}
freq->fr_CursorLine = cursor_line;
if (mode != MOVE_MODE_NO_OUTPUT && mode != MOVE_MODE_NO_CURSOR) {
hcomp_freq_cursor(freq);
print_info_line(INFO_LINE_MODE_NORMAL);
}
}
/* Check last changed date of directory for given file requester */
SHORT
check_date_stamp(struct FileRequest *freq, USHORT mode)
{
struct DateStamp *old_date = &freq->fr_Info.i_LastChanged,
*new_date = &fib->fib_Date;
SHORT error = VSH_STATUS_NORMAL;
if (freq->fr_Mode == FREQ_MODE_NORMAL && freq->fr_DirName[0] != '\0') {
if ((error = quiet_examine(freq->fr_DirLock, fib)) ==
VSH_STATUS_NORMAL) {
if (old_date->ds_Days != new_date->ds_Days || old_date->ds_Minute
!= new_date->ds_Minute || old_date->ds_Tick
!= new_date->ds_Tick) {
if (mode == READ_SAME_DIR_MODE_NO_READ) {
error = VSH_STATUS_READ_DIR; /* indicate to read same dir again */
} else {
error = read_same_dir(freq, mode);
}
}
}
}
return(error);
}
/* Set last changed date of directory for given file requester */
SHORT
set_date_stamp(struct FileRequest *freq)
{
SHORT error;
if ((error = quiet_examine(freq->fr_DirLock, fib)) == VSH_STATUS_NORMAL) {
CopyMem((BYTE *)&fib->fib_Date, (BYTE *)&freq->fr_Info.i_LastChanged,
(LONG)sizeof(struct DateStamp));
}
return(error);
}
/* Execute program with arguments */
SHORT
execute(BYTE *prog, BYTE *args)
{
BYTE cmd[MAX_DIR_NAME_LEN + MAX_FILE_NAME_LEN + 1], *ptr = &cmd[0];
SHORT error;
if (wshell_flag && FindPort("REXX") && *(USHORT *)((UBYTE *)DOSBase -
222) == 0x4ef9) {
*ptr++ = '['; /* needed for WShell + ARexx + patched Execute() vector */
}
*ptr++ = '"';
strcpy(ptr, prog);
ptr += strlen(prog);
*ptr++ = '"';
*ptr++ = ' ';
strcpy(ptr, args);
if (Execute(&cmd[0], nil_handle, Output()) == DOSFALSE) {
error = VSH_ERROR_EXECUTE_FAILED;
} else {
error = VSH_STATUS_NORMAL;
}
/*
Printf("Execute(%s)=%d\n", &cmd[0], error);
*/
return(error);
}
/* Find files or dirs by pattern, start from path in active freq */
SHORT
find(struct FileRequest *freq, BYTE *pattern)
{
struct AnchorPath *ap;
struct FileInfoBlock *info;
struct MinList *list;
struct FileNode *fnode;
BYTE *path, *path_buffer, *buffer;
LONG rc;
BPTR cd_lock;
BOOL keepon = TRUE;
SHORT error = VSH_STATUS_NORMAL;
print_fkey_text(FKEY_MODE_NONE);
freq->fr_Display.d_NumEntries = 0;
freq->fr_Display.d_FirstVisibleNode = NULL;
freq->fr_CursorLine = -1;
freq->fr_MarkedEntries = 0;
freq->fr_MarkedSize = 0;
freq->fr_Mode = FREQ_MODE_FIND;
if (!(list = (struct MinList *)AllocMem((LONG)sizeof(struct MinList),
MEMF_PUBLIC | MEMF_CLEAR))) {
error = VSH_ERROR_OUT_OF_MEM;
} else {
NewList((struct List *)list);
freq->fr_Display.d_List = list;
if (!(ap = (struct AnchorPath *)AllocMem((LONG)
(sizeof(struct AnchorPath) + MAX_DIR_NAME_LEN +
MAX_FILE_NAME_LEN + 1), MEMF_PUBLIC | MEMF_CLEAR))) {
error = VSH_ERROR_OUT_OF_MEM;
} else {
ap->ap_BreakBits = SIGBREAKF_CTRL_C;
ap->ap_StrLen = MAX_DIR_NAME_LEN + MAX_FILE_NAME_LEN;
ap->ap_Flags = APF_DoWild; /* traverse through ALL dirs */
info = &ap->ap_Info;
path = &ap->ap_Buf[0];
PreParse(pattern, &line1_buffer[0]);
pattern = &line1_buffer[0]; /* compiled pattern */
buffer = &path1_buffer[0];
cd_lock = CurrentDir(freq->fr_DirLock);
enable_abort = 1;
if (!(rc = FindFirst(star, ap))) {
do {
/* Check if entry matches pattern */
if ((info->fib_DirEntryType < 0 || (info->fib_DirEntryType > 0
&& !(ap->ap_Flags & APF_DidDir))) &&
PatternMatch(pattern, &info->fib_FileName[0]) ==
TRUE) {
/* Build full path name and display it in status line */
if ((error = build_path_name_from_relative_path(buffer,
path)) != VSH_STATUS_NORMAL) {
keepon = FALSE;
} else {
print_dos_status(DOS_MODE_FIND, buffer, NULL);
/* Strip file name from path and build file node from it */
*(BaseName(buffer) - 1) = '\0';
if (!(path_buffer = DosAllocMem((LONG)(strlen(buffer) +
1)))) {
keepon = FALSE;
error = VSH_ERROR_OUT_OF_MEM;
} else {
if (!(fnode = build_file_node(info))) {
keepon = FALSE;
error = VSH_ERROR_OUT_OF_MEM;
} else {
strcpy(path_buffer, buffer);
fnode->fn_Path = path_buffer;
insert_file_node(fnode, list);
}
}
}
}
/* If directory then check if already scanned */
if (info->fib_DirEntryType > 0) {
if (ap->ap_Flags & APF_DidDir) {
ap->ap_Flags &= ~APF_DidDir; /* don't enter dir again */
} else {
ap->ap_Flags |= APF_DoDir; /* enter dir */
}
}
} while (keepon == TRUE && !(rc = FindNext(ap)));
}
enable_abort = 0;
FreeAnchorChain(ap);
CurrentDir(cd_lock);
if (error == VSH_STATUS_NORMAL) {
switch (rc) {
case ERROR_BREAK :
error = VSH_ERROR_ABORTED;
case ERROR_NO_MORE_ENTRIES :
if (freq->fr_Display.d_NumEntries =
count_file_nodes(list)) {
freq->fr_Display.d_FirstVisibleNode = list->mlh_Head;
freq->fr_CursorLine = 0;
}
break;
default :
error = VSH_ERROR_FINDFIRST_OR_FINDNEXT_FAILED;
break;
}
}
FreeMem(ap, (LONG)(sizeof(struct AnchorPath) + MAX_DIR_NAME_LEN +
MAX_FILE_NAME_LEN + 1));
}
}
return(error);
}
/* Clear console read buffer */
VOID
clear_input_line(VOID)
{
if ((struct CommandLineInterface *)BADDR(_parent_proc->pr_CLI) ==
save_cli) { /* no EndCLI ? */
dos_packet(con_input_fhandle->fh_Type, (LONG)ACTION_FLUSH);
}
}
/* Force string into command line */
SHORT
force_string(BYTE *string, USHORT len, USHORT mode)
{
BYTE *path = &path2_buffer[0];
SHORT error = VSH_STATUS_NORMAL;
if ((struct CommandLineInterface *)BADDR(_parent_proc->pr_CLI) ==
save_cli) { /* no EndCLI ? */
if (mode == FORCE_MODE_NEWLINE_APPEND || mode ==
FORCE_MODE_NEWLINE_COPY) {
if (dos_packet(con_input_fhandle->fh_Type, (LONG)ACTION_FLUSH) ==
DOSFALSE) {
error = VSH_ERROR_WRONG_CONMAN_VERSION;
} else {
if (mode == FORCE_MODE_NEWLINE_APPEND) {
*(string + len++) = '\n'; /* append new line char */
} else {
strncpy(path, string, (size_t)len); /* copy string with new line char */
*(path + len++) = (BYTE)'\n';
string = path;
}
}
}
if (error == VSH_STATUS_NORMAL) {
if (dos_packet(con_input_fhandle->fh_Type, CONMAN_ACTION_FORCE,
con_input_fhandle, string, (LONG)len) == DOSFALSE) {
error = VSH_ERROR_WRONG_CONMAN_VERSION;
}
}
}
return(error);
}