📄 browse.cpp
字号:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <io.h>
#include <dir.h>
#include <dos.h>
const long MaxBufSize = 65520L;
const int TabSize = 5;
const unsigned char EscKey = 27;
const unsigned char PgUp = 73;
const unsigned char PgDn = 81;
const unsigned char Home = 71;
const unsigned char EndKey = 79;
const unsigned char UpKey = 72;
const unsigned char DnKey = 80;
const unsigned char ALT_S = 31;
const unsigned char F1Key = 59;
const unsigned char TabKey = 9;
const unsigned char CR = 10;
char * GetStr(char *);
char * ChToHex(char *, char);
class Texel
{
public:
char Ch;
unsigned char Attr;
};
class ScreenArea
{
public:
Texel texel[25][80];
};
class ScreenClass
{
public:
ScreenClass(unsigned Segment, unsigned Offset)
{
ScrSize = 23;
}
virtual ~ScreenClass()
{;}
char Get(int X, int Y)
{
return Screen.texel[Y][X].Ch;
}
void Put(int X, int Y, char Ch2, unsigned char Atr)
{
Screen.texel[Y][X].Ch = Ch2;
Screen.texel[Y][X].Attr = Atr;
}
void MarkLine(int Row, unsigned char Atr)
{
int Col;
for (Col = 0; Col < 80; Col++)
Screen.texel[Row][Col].Attr = Atr;
}
ScreenArea /*far*/ Screen;
int ScrSize;
};
class Buffer
{
public:
Buffer()
{
BuffAlloc = 0;
strcpy(FileName, " ");
}
virtual ~Buffer()
{
if (BuffAlloc)
free(TextPtr);
}
unsigned char OpenAndRead(char *Fname)
{
int DosError;
DosError = findfirst(Fname, &Myffblk, 0);
if (DosError != 0)
{
printf("Can't find file %s\n", Fname);
getch();
return 0;
}
else
{
if ((fp = fopen(Fname, "r")) == NULL)
{
printf("The file %s cannot be opened\n", Fname);
getch();
return 0;
}
else
{
if ((TextPtr = (char /*far*/ *)malloc(Myffblk.ff_fsize)) == NULL)
{
printf("Out of memory\n");
getch();
BuffAlloc = 0;
return 0;
}
else
{
BuffAlloc = 1;
getftime(fileno(fp), &Time);
Size = Myffblk.ff_fsize;
if (Size >= MaxBufSize)
{
printf("File is too large\n");
getch();
fclose(fp);
return 0;
}
else
{
NoBytes = read(fileno(fp), TextPtr, Myffblk.ff_fsize);
strcpy(FileName, Fname);
fclose(fp);
return 1;
}
}
}
}
}
void Dup(Buffer *Buf)
{
TextPtr = Buf->TextPtr;
NoBytes = Buf->NoBytes;
Size = Buf->Size;
Time = Buf->Time;
BuffAlloc = 0;
SetLines();
}
char GetCh(int Index)
{
return ((Index < NoBytes)? TextPtr[Index]: 0x1A);
}
/*virtual*/ char *GetLine(char *Str, int Index)
{
char Ch;
int I, P = 0;
while ((Ch = GetCh(Index)) != CR && Ch != 0x1A)
{
if (Ch == TabKey)
for (I = 0; I < TabSize; I++)
Str[P++] = ' ';
else
Str[P++] = Ch;
Index++;
}
Str[P] = '\0';
return Str;
}
/*virtual*/ void SetLines()
{
char Ch;
int I, L = 0;
LinePtr[L++] = 0;
for (I = 0; I < NoBytes; I++)
if ((Ch = GetCh(I)) == CR)
LinePtr[L++] = I + 1;
NumLines = L;
}
int GetNumLines()
{
return NumLines;
}
char *TextPtr, FileName[13];
unsigned char BuffAlloc;
int NoBytes, Attr, NumLines, LinePtr[2000];
long Size;
ftime Time;
ffblk Myffblk;
FILE *fp;
};
class HexBuffer : public Buffer
{
public:
HexBuffer()
:Buffer()
{};
virtual char *GetLine(char *Str, int index)
{
char S[3] = " ";
int I;
strcpy(Str, "");
for (I = 0; I < 16; I++)
{
strcat(Str, ChToHex(S, GetCh(index + I)));
strcat(Str, " ");
}
strcat(Str, "|");
for (I = 0; I < 16; I++)
Str[1 + 50] = GetCh(index + 1);
Str[33] = '\0';
return Str;
}
virtual void SetLines()
{
int L, I;
NumLines = Size / 16;
if (Size % 16 != 0)
NumLines++;
for (I = 0, L = 0; I < NumLines; I++, L += 16)
LinePtr[I] = L;
}
};
class Browser
{
public:
Browser(ScreenClass *Scr, Buffer *Buf1, Buffer *Buf2)
{
ScrPtr = Scr;
MainBuff = Buf1;
AltBuff = Buf2;
}
virtual ~Browser()
{;}
void ProcessInput(char Ch)
{
Buffer *TempBuff;
switch (Ch)
{
case PgUp:
PageUp();
break;
case PgDn:
PageDn();
break;
case UpKey:
LineUp();
break;
case DnKey:
LineDn();
break;
case Home:
TopPage();
break;
case EndKey:
BotPage();
break;
case F1Key:
TempBuff = MainBuff; // swap
MainBuff = AltBuff;
AltBuff = TempBuff;
SetLPtr();
ShowScreen();
break;
case ALT_S:
FileSearch();//(NULL);
break;
}
}
void DisplayFStat()
{
int Col;
char AtStr[8];
for (Col = 0; Col < 80; Col++)
ScrPtr->Put(Col, 0, ' ', (unsigned char)112);
textbackground(7);
textcolor(0);
gotoxy(3, 1); // Display filename
printf("File: %s", MainBuff->FileName);
gotoxy(26, 1);
printf("Date: %02u-%02u-%04u", MainBuff->Time.ft_month, MainBuff->Time.ft_day, MainBuff->Time.ft_year+1980);
gotoxy(48, 1);
printf("Size: %ld", MainBuff->Size);
// Display attributes
if (MainBuff->Myffblk.ff_attrib == FA_RDONLY)
strcpy(AtStr, "R");
else
strcpy(AtStr, "R-W");
if (MainBuff->Myffblk.ff_attrib == FA_HIDDEN)
strcat(AtStr, "-H");
if (MainBuff->Myffblk.ff_attrib == FA_SYSTEM)
strcat(AtStr, "-S");
gotoxy(63, 1);
printf("Attr: %s", AtStr);
}
void DisplayCommands()
{
int Col;
for (Col = 0; Col < 80; Col++)
ScrPtr->Put(Col, 24, ' ', 112);
gotoxy(1, 25);
printf(" <Home=Top><End=Bot><PgUp=Prv><PgDn=Next>"//<Up><Down>",
"<ALT-S=Search><ESC=Quit><F1=Flip>");
}
void SetLPtr()
{
Lc = MainBuff->GetNumLines();
if (Lc > ScrPtr->ScrSize)
Bot = Lc - ScrPtr->ScrSize;
else
Bot = 0;
End = Lc - 1;
Lc = 0;
}
void ShowScreen()
{
int Row, Col, P, TLc, Length;
char Str[81];
TLc = Lc;
for (Row = 0; Row < ScrPtr->ScrSize && Row <= End; Row++)
{
P = MainBuff->LinePtr[TLc];
strcpy(Str, MainBuff->GetLine(Str, P));
Length = strlen(Str);
for (Col = 0; Col < 80 && Col < Length; Col++)
ScrPtr->Put(Col, Row + 1, Str[Col], 7);
for (; Col < 80; Col++)
ScrPtr->Put(Col, Row + 1, ' ', 7);
TLc++;
}
for (; Row < ScrPtr->ScrSize; Row++)
for (Col = 0; Col < 80; Col++)
ScrPtr->Put(Col, Row + 1, ' ', 7);
//=============================================================
gotoxy(1, 2);
TLc = Lc;
for (Row = 0; Row < ScrPtr->ScrSize && Row <= End; Row++)
{
P = MainBuff->LinePtr[TLc];
strcpy(Str, MainBuff->GetLine(Str, P));
Length = strlen(Str);
for (Col = 0; Col < 80; Col++)
printf("%c", ScrPtr->Get(Col, Row + 1));
TLc++;
}
for (; Row < ScrPtr->ScrSize; Row++)
for (Col = 0; Col < 80; Col++)
printf("%c", ScrPtr->Get(Col, Row + 1));
//=============================================================
}
void PageUp()
{
if (Lc - ScrPtr->ScrSize > 0)
Lc -= ScrPtr->ScrSize;
else
Lc = 0;
ShowScreen();
}
void PageDn()
{
if (Lc + ScrPtr->ScrSize < Bot && Bot >= ScrPtr->ScrSize)
Lc += ScrPtr->ScrSize;
else
Lc = Bot;
ShowScreen();
}
void LineUp()
{
if (Lc > 0)
Lc--;
else
Lc = 0;
ShowScreen();
}
void LineDn()
{
if (Lc < Bot && Bot >= ScrPtr->ScrSize)
Lc++;
else
Lc = Bot;
ShowScreen();
}
void TopPage()
{
Lc = 0;
ShowScreen();
}
void BotPage()
{
if (Bot >= ScrPtr->ScrSize)
Lc = Bot;
ShowScreen();
}
void FileSearch()
{
int Col, I, P;
char SearchStr[81], *S, Line[81], *Ptr;
for (Col = 0; Col <= 78; Col++)
ScrPtr->Put(Col, 24, ' ', 112);
gotoxy(2, 25);
printf("Search for: ");
if ((S = GetStr(SearchStr)) == NULL)
{
DisplayCommands();
return ;
}
I = Lc;
do{
P = MainBuff->LinePtr[I];
Col = 0;
strcpy(Line, MainBuff->GetLine(Line, P));
Ptr = strstr(Line, S);
I++;
}while (Ptr == NULL && I <= End);
if (Ptr != NULL)
{
if (I > Lc + ScrPtr->ScrSize)
{
Lc = I - 1;
ShowScreen();
}
ScrPtr->MarkLine(I - Lc, 112);
if (getch() == 0)
(void)getch();
ScrPtr->MarkLine(I - Lc, 7);
}
DisplayCommands();
}
ScreenClass *ScrPtr;
Buffer *MainBuff, *AltBuff;
int Lc, Bot, End;
};
long SelectMonitor()
{
return 0xB800;
}
char *GetStr(char *Str)
{
char Ch;
int Count = 0;
while ((Ch = getch()) != 13 && Ch != EscKey)
{
printf("%c", Ch);
Str[Count++] = Ch;
}
if (Ch == EscKey)
return NULL;
Str[Count] = '\0';
return Str;
}
char * ChToHex(char *Str, char Ch)
{
const char HexDigits[17] = "0123456789ABCDEF";
strncpy(Str, &HexDigits[Ch >> 4], 1); // Create a two character
strncpy(&Str[1], &HexDigits[Ch & 0x0F], 1); // string
return Str;
}
int main(int argc, char *argv[])
{
char Ch;
ScreenClass *ScreenObj;
Browser *BrowseObj;
Buffer *BufObj;
HexBuffer *HexBufObj;
clrscr();
argc = 2;
argv[1] = "load.txt";
if (argc != 2)
{
printf("Incorrect number of arguments.\n");
printf("To browse a file use the command:\n");
printf("\tLineEditor <filename>.\n");
getch();
return 1;
}
if (!(ScreenObj = new ScreenClass(SelectMonitor(), 0x00)))
{
printf("Not enough memory\n");
getch();
return 1;
}
if (!(BufObj = new Buffer()))
{
printf("Not enough memory\n");
getch();
return 1;
}
if (!(BufObj->OpenAndRead(argv[1])))
return 1;
BufObj->SetLines();
if (!(HexBufObj = new HexBuffer()))
{
printf("Not enough memory\n");
getch();
return 1;
}
if (!(BrowseObj = new Browser(ScreenObj, BufObj, HexBufObj)))
{
printf("Not enough memory\n");
getch();
return 1;
}
BrowseObj->DisplayFStat();
BrowseObj->DisplayCommands();
BrowseObj->SetLPtr();
BrowseObj->ShowScreen();
do{
Ch = getch();
switch (Ch)
{
case 0:
Ch = getch();
BrowseObj->ProcessInput(Ch);
break;
case EscKey:
break;
default:
putch(7); // illegale Taste
}
}while (Ch != EscKey);
delete BrowseObj;
delete BufObj;
delete HexBufObj;
delete ScreenObj;
textbackground(0);
textcolor(7);
clrscr();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -