This repository has been archived on 2023-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
fte/o_directory.cpp

455 lines
11 KiB
C++
Raw Permalink Normal View History

/* o_directory.cpp
*
* Copyright (c) 1994-1996, Marko Macek
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
*/
#define NEED_LOG_H
#include "fte.h"
#ifdef CONFIG_OBJ_DIRECTORY
EDirectory::EDirectory(int createFlags, EModel **ARoot, char *aPath): EList(createFlags, ARoot, aPath) {
char XPath[MAXPATH];
Files = 0;
FCount = 0;
SearchLen = 0;
ExpandPath(aPath, XPath);
Slash(XPath, 1);
Path = strdup(XPath);
RescanList();
}
EDirectory::~EDirectory() {
if (Files) {
for (int i = 0; i < FCount; i++)
delete Files[i];
free(Files);
}
free(Path);
}
EEventMap *EDirectory::GetEventMap() {
return FindEventMap("DIRECTORY");
}
void EDirectory::DrawLine(PCell B, int Line, int Col, ChColor color, int Width) {
char s[1024];
MoveCh(B, ' ', color, Width);
if (Files && Line >= 0 && Line < FCount) {
int Year, Mon, Day, Hour, Min, Sec;
struct tm *t;
time_t tim;
tim = Files[Line]->MTime();
t = localtime(&tim);
if (t) {
Year = t->tm_year + 1900;
Mon = t->tm_mon + 1;
Day = t->tm_mday;
Hour = t->tm_hour;
Min = t->tm_min;
Sec = t->tm_sec;
} else {
Year = Mon = Day = Hour = Min = Sec = 0;
}
sprintf(s,
" %04d/%02d/%02d %02d:%02d:%02d %8ld ",
Year, Mon, Day, Hour, Min, Sec,
Files[Line]->Size());
strcat(s, Files[Line]->Name());
s[strlen(s) + 1] = '\0';
s[strlen(s)] = (Files[Line]->Type() == fiDIRECTORY)? SLASH : ' ';
if (Col < int(strlen(s)))
MoveStr(B, 0, Width, s + Col,
(Files[Line]->Type() == fiDIRECTORY) ?
(TAttr)(color | (1<<3)) : (TAttr)color, Width);
}
}
int _LNK_CONV FileNameCmp(const void *a, const void *b) {
FileInfo *A = *(FileInfo **)a;
FileInfo *B = *(FileInfo **)b;
if (!(A->Type() == fiDIRECTORY) && (B->Type() == fiDIRECTORY))
return 1;
if ((A->Type() == fiDIRECTORY) && !(B->Type() == fiDIRECTORY))
return -1;
return filecmp(A->Name(), B->Name());
}
void EDirectory::RescanList() {
char Dir[256];
char Name[256];
int DirCount = 0;
int SizeCount = 0;
FileFind *ff;
FileInfo *fi;
int rc;
if (Files)
FreeList();
Count = 0;
FCount = 0;
if (JustDirectory(Path, Dir) != 0) return;
JustFileName(Path, Name);
ff = new FileFind(Dir, "*", ffDIRECTORY | ffHIDDEN);
if (ff == 0)
return ;
rc = ff->FindFirst(&fi);
while (rc == 0) {
assert(fi != 0);
if (strcmp(fi->Name(), ".") != 0) {
Files = (FileInfo **)realloc((void *)Files, ((FCount | 255) + 1) * sizeof(FileInfo *));
if (Files == 0)
{
delete fi;
delete ff;
return;
}
Files[FCount] = fi;
SizeCount += Files[FCount]->Size();
if (fi->Type() == fiDIRECTORY && (strcmp(fi->Name(), "..") != 0))
DirCount++;
Count++;
FCount++;
} else
delete fi;
rc = ff->FindNext(&fi);
}
delete ff;
{
char CTitle[256];
sprintf(CTitle, "%d files%c%d dirs%c%d bytes%c%-200.200s",
FCount, ConGetDrawChar(DCH_V),
DirCount, ConGetDrawChar(DCH_V),
SizeCount, ConGetDrawChar(DCH_V),
Dir);
SetTitle(CTitle);
}
qsort(Files, FCount, sizeof(FileInfo *), FileNameCmp);
NeedsRedraw = 1;
}
void EDirectory::FreeList() {
if (Files) {
for (int i = 0; i < FCount; i++)
delete Files[i];
free(Files);
}
Files = 0;
FCount = 0;
}
int EDirectory::isDir(int No) {
char FilePath[256];
JustDirectory(Path, FilePath);
Slash(FilePath, 1);
strcat(FilePath, Files[No]->Name());
return IsDirectory(FilePath);
}
int EDirectory::ExecCommand(int Command, ExState &State) {
switch (Command) {
case ExActivateInOtherWindow:
SearchLen = 0;
Msg(S_INFO, "");
if (Files && Row >= 0 && Row < FCount) {
if (isDir(Row)) {
} else {
return FmLoad(Files[Row]->Name(), View->Next);
}
}
return ErFAIL;
case ExRescan:
if (RescanDir() == 0)
return ErFAIL;
return ErOK;
case ExDirGoUp:
SearchLen = 0;
Msg(S_INFO, "");
FmChDir(SDOT SDOT);
return ErOK;
case ExDirGoDown:
SearchLen = 0;
Msg(S_INFO, "");
if (Files && Row >= 0 && Row < FCount) {
if (isDir(Row)) {
FmChDir(Files[Row]->Name());
return ErOK;
}
}
return ErFAIL;
case ExDirGoto:
SearchLen = 0;
Msg(S_INFO, "");
return ChangeDir(State);
case ExDirGoRoot:
SearchLen = 0;
Msg(S_INFO, "");
FmChDir(SSLASH);
return ErOK;
case ExDeleteFile:
SearchLen = 0;
Msg(S_INFO, "");
return FmRmDir(Files[Row]->Name());
}
return EList::ExecCommand(Command, State);
}
int EDirectory::Activate(int No) {
SearchLen = 0;
Msg(S_INFO, "");
if (Files && No >= 0 && No < FCount) {
if (isDir(No)) {
FmChDir(Files[No]->Name());
return 0;
} else {
return FmLoad(Files[No]->Name(), View);
}
}
return 1;
}
void EDirectory::HandleEvent(TEvent &Event) {
STARTFUNC("EDirectory::HandleEvent");
int resetSearch = 0;
EModel::HandleEvent(Event);
switch (Event.What) {
case evKeyDown:
LOG << "Key Code: " << kbCode(Event.Key.Code) << ENDLINE;
resetSearch = 1;
switch (kbCode(Event.Key.Code)) {
case kbBackSp:
LOG << "Got backspace" << ENDLINE;
resetSearch = 0;
if (SearchLen > 0) {
SearchName[--SearchLen] = 0;
Row = SearchPos[SearchLen];
Msg(S_INFO, "Search: [%s]", SearchName);
} else
Msg(S_INFO, "");
break;
case kbEsc:
Msg(S_INFO, "");
break;
default:
resetSearch = 0; // moved here - its better for user
// otherwice there is no way to find files like i_ascii
if (isAscii(Event.Key.Code) && (SearchLen < MAXISEARCH)) {
char Ch = (char) Event.Key.Code;
int Found;
LOG << " -> " << BinChar(Ch) << ENDLINE;
SearchPos[SearchLen] = Row;
SearchName[SearchLen] = Ch;
SearchName[++SearchLen] = 0;
Found = 0;
LOG << "Comparing " << SearchName << ENDLINE;
for (int i = Row; i < FCount; i++) {
LOG << " to -> " << Files[i]->Name() << ENDLINE;
if (strnicmp(SearchName, Files[i]->Name(), SearchLen) == 0) {
Row = i;
Found = 1;
break;
}
}
if (Found == 0)
SearchName[--SearchLen] = 0;
Msg(S_INFO, "Search: [%s]", SearchName);
}
break;
}
}
if (resetSearch) {
SearchLen = 0;
}
LOG << "SearchLen = " << SearchLen << ENDLINE;
}
int EDirectory::RescanDir() {
char CName[256] = "";
if (Row >= 0 && Row < FCount)
strcpy(CName, Files[Row]->Name());
Row = 0;
RescanList();
if (CName[0] != 0) {
for (int i = 0; i < FCount; i++) {
if (filecmp(Files[i]->Name(), CName) == 0)
{
Row = i;
break;
}
}
}
return 1;
}
int EDirectory::FmChDir(const char *Name) {
char Dir[256];
char CName[256] = "";
if (strcmp(Name, SSLASH) == 0) {
JustRoot(Path, Dir);
} else if (strcmp(Name, SDOT SDOT) == 0) {
Slash(Path, 0);
JustFileName(Path, CName);
JustDirectory(Path, Dir);
} else {
JustDirectory(Path, Dir);
Slash(Dir, 1);
strcat(Dir, Name);
}
Slash(Dir, 1);
free(Path);
Path = strdup(Dir);
Row = 0;
RescanList();
if (CName[0] != 0) {
for (int i = 0; i < FCount; i++) {
if (filecmp(Files[i]->Name(), CName) == 0)
{
Row = i;
break;
}
}
}
UpdateTitle();
return 1;
}
int EDirectory::FmRmDir(char const* Name)
{
char FilePath[256];
strcpy(FilePath, Path);
Slash(FilePath, 1);
strcat(FilePath, Name);
int choice =
View->MView->Win->Choice(GPC_CONFIRM,
"Remove File",
2, "O&K", "&Cancel",
"Remove %s?", Name);
if (choice == 0)
{
if (unlink(FilePath) == 0)
{
// put the cursor to the previous row
--Row;
// There has to be a more efficient way of doing this ...
return RescanDir();
}
else
{
Msg(S_INFO, "Failed to remove %s", Name);
return 0;
}
}
else
{
Msg(S_INFO, "Cancelled");
return 0;
}
}
int EDirectory::FmLoad(char *Name, EView *XView) {
char FilePath[256];
JustDirectory(Path, FilePath);
Slash(FilePath, 1);
strcat(FilePath, Name);
return FileLoad(0, FilePath, NULL, XView);
}
void EDirectory::GetName(char *AName, int MaxLen) {
strncpy(AName, Path, MaxLen);
AName[MaxLen - 1] = 0;
Slash(AName, 0);
}
void EDirectory::GetPath(char *APath, int MaxLen) {
strncpy(APath, Path, MaxLen);
APath[MaxLen - 1] = 0;
Slash(APath, 0);
}
void EDirectory::GetInfo(char *AInfo, int MaxLen) {
sprintf(AInfo,
"%2d %04d/%03d %-150s",
ModelNo,
Row + 1, FCount,
Path);
}
void EDirectory::GetTitle(char *ATitle, int MaxLen, char *ASTitle, int SMaxLen) {
strncpy(ATitle, Path, MaxLen - 1);
ATitle[MaxLen - 1] = 0;
{
char P[MAXPATH];
strcpy(P, Path);
Slash(P, 0);
JustDirectory(P, ASTitle);
Slash(ASTitle, 1);
}
}
int EDirectory::ChangeDir(ExState &State) {
char Dir[MAXPATH];
char Dir2[MAXPATH];
if (State.GetStrParam(View, Dir, sizeof(Dir)) == 0) {
strcpy(Dir, Path);
if (View->MView->Win->GetStr("Set directory", sizeof(Dir), Dir, HIST_PATH) == 0)
return 0;
}
if (ExpandPath(Dir, Dir2) == -1)
return 0;
#if 0
// is this needed for other systems as well ?
Slash(Dir2, 1);
#endif
if (Path)
free(Path);
Path = strdup(Dir2);
Row = -1;
UpdateTitle();
return RescanDir();
}
int EDirectory::GetContext() { return CONTEXT_DIRECTORY; }
char *EDirectory::FormatLine(int Line) { return 0; };
int EDirectory::CanActivate(int Line) { return 1; }
#endif