381 lines
9.5 KiB
C
381 lines
9.5 KiB
C
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <windows.h>
|
||
|
#include "list.h"
|
||
|
|
||
|
static char ReMap [256];
|
||
|
#define FOUND 0
|
||
|
#define NOT_FOUND 1
|
||
|
#define ABORT 2
|
||
|
|
||
|
int
|
||
|
GetNewFile ()
|
||
|
{
|
||
|
char FileName [160];
|
||
|
struct Flist *pOrig;
|
||
|
|
||
|
SyncReader ();
|
||
|
GetInput ("File...> ", FileName, 160);
|
||
|
if (FileName[0] == 0) {
|
||
|
SetUpdate (U_HEAD);
|
||
|
SetEvent (vSemReader);
|
||
|
return (0);
|
||
|
}
|
||
|
pOrig = vpFlCur;
|
||
|
AddFileToList (FileName);
|
||
|
vpFlCur = pOrig;
|
||
|
SetEvent (vSemReader);
|
||
|
return (1);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
GetSearchString ()
|
||
|
{
|
||
|
UpdateHighClear ();
|
||
|
GetInput ("String.> ", vSearchString, 40);
|
||
|
InitSearchReMap ();
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
InitSearchReMap ()
|
||
|
{
|
||
|
unsigned i;
|
||
|
|
||
|
if (vStatCode & S_NOCASE)
|
||
|
_strupr (vSearchString);
|
||
|
|
||
|
/*
|
||
|
* Build ReMap
|
||
|
*/
|
||
|
for (i=0; i < 256; i++)
|
||
|
ReMap[i] = (char)i;
|
||
|
|
||
|
if (vStatCode & S_NOCASE)
|
||
|
for (i='a'; i <= 'z'; i++)
|
||
|
ReMap[i] = (char)(i - ('a' - 'A'));
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
FindString()
|
||
|
{
|
||
|
char eof, dir_next;
|
||
|
long offset, lrange, line, l, hTopLine;
|
||
|
struct Flist *phCurFile, *pFile;
|
||
|
|
||
|
if (vSearchString[0] == 0) {
|
||
|
SetUpdate (U_HEAD);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
SetUpdate (U_NONE);
|
||
|
DisLn (CMDPOS, (Uchar)(vLines+1), "Searching");
|
||
|
vStatCode |= S_INSEARCH;
|
||
|
dir_next = (char)(vStatCode & S_NEXT);
|
||
|
|
||
|
/*
|
||
|
* Get starting point for search in the current file.
|
||
|
* Save current file, and location.
|
||
|
*/
|
||
|
hTopLine = vTopLine;
|
||
|
phCurFile = vpFlCur;
|
||
|
|
||
|
if (vHighTop >= 0L)
|
||
|
vTopLine = vHighTop;
|
||
|
if (vStatCode & S_NEXT)
|
||
|
vTopLine++;
|
||
|
if (vTopLine >= vNLine)
|
||
|
vTopLine = vNLine-1;
|
||
|
|
||
|
QuickRestore (); /* Jump to starting line */
|
||
|
|
||
|
for (; ;) {
|
||
|
/*
|
||
|
* Make sure starting point is in memory
|
||
|
*/
|
||
|
while (InfoReady () == 0) { /* Set extern values */
|
||
|
ResetEvent (vSemMoreData);
|
||
|
SetEvent (vSemReader);
|
||
|
WaitForSingleObject(vSemMoreData, WAITFOREVER);
|
||
|
ResetEvent(vSemMoreData);
|
||
|
}
|
||
|
|
||
|
if (! dir_next) {
|
||
|
if (vOffTop)
|
||
|
vOffTop--;
|
||
|
else if (vpBlockTop->prev) {
|
||
|
vpBlockTop = vpBlockTop->prev;
|
||
|
vOffTop = vpBlockTop->size;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vTopLine = 1L;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Do the search.
|
||
|
* Use 2 different routines, for speed.
|
||
|
*
|
||
|
* Uses vpBlockTop & vOffTop. They are set up by setting TopLine
|
||
|
* then calling InfoReady.
|
||
|
*/
|
||
|
eof = (char)SearchText (dir_next);
|
||
|
|
||
|
if (eof != FOUND)
|
||
|
vTopLine = hTopLine;
|
||
|
|
||
|
/* Multi-file search? Yes, go onto next file */
|
||
|
if (eof == NOT_FOUND && (vStatCode & S_MFILE)) {
|
||
|
if (vStatCode & S_NEXT) {
|
||
|
if ( (pFile = vpFlCur->next) == NULL)
|
||
|
break;
|
||
|
NextFile (0, pFile); /* Get file */
|
||
|
hTopLine = vTopLine; /* Save position */
|
||
|
vTopLine = line = 0; /* Set search position */
|
||
|
} else {
|
||
|
if ( (pFile = vpFlCur->prev) == NULL)
|
||
|
break;
|
||
|
NextFile (0, pFile);
|
||
|
hTopLine = vTopLine;
|
||
|
if (vLastLine == NOLASTLINE) { /* HACK. if EOF is unkown */
|
||
|
dir_next = S_NEXT; /* goto prev file, but scan */
|
||
|
vTopLine = line = 0; /* from TOF to EOF */
|
||
|
} else {
|
||
|
vTopLine = (line = vLastLine) - vLines;
|
||
|
dir_next = 0; /* else, scan from EOF to */
|
||
|
if (vTopLine < 0) /* TOF. */
|
||
|
vTopLine = 0;
|
||
|
}
|
||
|
}
|
||
|
QuickRestore (); /* Display 1 page of new */
|
||
|
SetUpdate (U_ALL); /* new file. then set scan */
|
||
|
SetUpdate (U_NONE); /* position */
|
||
|
vTopLine = line;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
break; /* Done searching */
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* If not found (or abort), then resotre position
|
||
|
*/
|
||
|
vStatCode &= ~S_INSEARCH;
|
||
|
if (eof) {
|
||
|
if (phCurFile != vpFlCur) /* Restore file & position */
|
||
|
NextFile (0, phCurFile);
|
||
|
QuickRestore ();
|
||
|
|
||
|
SetUpdate (U_ALL); /* Force screen update, to fix */
|
||
|
SetUpdate (U_NONE); /* scroll bar position. */
|
||
|
DisLn (CMDPOS, (Uchar)(vLines+1), eof == 1 ? "* Text not found *" : "* Aborting Search *");
|
||
|
if (eof == 1)
|
||
|
beep ();
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
// Search routine adjusts vpBlockTop & vOffTop to next(prev)
|
||
|
// occurance of string. Now the line # must be set.
|
||
|
|
||
|
offset = vpBlockTop->offset + vOffTop;
|
||
|
|
||
|
lrange = vNLine/4 + 2;
|
||
|
line = vNLine/2;
|
||
|
while (lrange > 4L) {
|
||
|
l = vprgLineTable[line/PLINES][line%PLINES];
|
||
|
if (l < offset) {
|
||
|
if ( (line += lrange) > vNLine)
|
||
|
line = vNLine;
|
||
|
} else {
|
||
|
if ( (line -= lrange) < 0L)
|
||
|
line = 0L;
|
||
|
}
|
||
|
/* lrange >>= 1; */
|
||
|
lrange = (lrange>>1) + 1;
|
||
|
}
|
||
|
line += 7;
|
||
|
|
||
|
while (vprgLineTable[line/PLINES][line%PLINES] > offset)
|
||
|
line--;
|
||
|
|
||
|
vHighTop = line;
|
||
|
vHighLen = 0;
|
||
|
|
||
|
/*
|
||
|
* Was found. Adjust to be in center of CRT
|
||
|
*/
|
||
|
GoToMark ();
|
||
|
}
|
||
|
|
||
|
int
|
||
|
SearchText (
|
||
|
char dir
|
||
|
)
|
||
|
{
|
||
|
char *data;
|
||
|
char *data1;
|
||
|
int i;
|
||
|
Uchar c, d;
|
||
|
|
||
|
for (; ;) {
|
||
|
data = vpBlockTop->Data;
|
||
|
data += vOffTop;
|
||
|
|
||
|
if (ReMap [(unsigned char)*data] == vSearchString[0]) {
|
||
|
data1 = data;
|
||
|
i = vOffTop;
|
||
|
d = 1;
|
||
|
for (; ;) {
|
||
|
c = vSearchString[d++];
|
||
|
if (c == 0)
|
||
|
return (FOUND);
|
||
|
|
||
|
if (++i >= BLOCKSIZE) {
|
||
|
while (vpBlockTop->next == NULL) {
|
||
|
vpCur = vpBlockTop;
|
||
|
vReaderFlag = F_DOWN;
|
||
|
SetEvent (vSemReader);
|
||
|
WaitForSingleObject(vSemMoreData, WAITFOREVER);
|
||
|
ResetEvent(vSemMoreData);
|
||
|
}
|
||
|
i = 0;
|
||
|
|
||
|
data1 = vpBlockTop->next->Data;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
data1++;
|
||
|
}
|
||
|
|
||
|
if (ReMap [(unsigned char)*data1] != (char)c)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (dir) {
|
||
|
vOffTop++;
|
||
|
if (vOffTop >= BLOCKSIZE) {
|
||
|
if (vpBlockTop->flag == F_EOF)
|
||
|
return (NOT_FOUND);
|
||
|
fancy_percent ();
|
||
|
if (_abort ())
|
||
|
return (ABORT);
|
||
|
while (vpBlockTop->next == NULL) {
|
||
|
vpCur = vpBlockTop;
|
||
|
vReaderFlag = F_DOWN;
|
||
|
SetEvent (vSemReader);
|
||
|
WaitForSingleObject(vSemMoreData, WAITFOREVER);
|
||
|
ResetEvent(vSemMoreData);
|
||
|
}
|
||
|
vOffTop = 0;
|
||
|
vpBlockTop = vpBlockTop->next;
|
||
|
}
|
||
|
} else {
|
||
|
vOffTop--;
|
||
|
if (vOffTop < 0) {
|
||
|
if (vpBlockTop->offset == 0L)
|
||
|
return (NOT_FOUND);
|
||
|
fancy_percent ();
|
||
|
if (_abort ())
|
||
|
return (ABORT);
|
||
|
while (vpBlockTop->prev == NULL) {
|
||
|
vpCur = vpBlockTop;
|
||
|
vReaderFlag = F_UP;
|
||
|
SetEvent (vSemReader);
|
||
|
WaitForSingleObject(vSemMoreData, WAITFOREVER);
|
||
|
ResetEvent(vSemMoreData);
|
||
|
}
|
||
|
vOffTop = BLOCKSIZE - 1;
|
||
|
vpBlockTop = vpBlockTop->prev;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
GoToMark ()
|
||
|
{
|
||
|
long line;
|
||
|
|
||
|
if (vHighTop < 0L)
|
||
|
return ;
|
||
|
|
||
|
line = vHighTop;
|
||
|
UpdateHighClear ();
|
||
|
|
||
|
vTopLine = 1;
|
||
|
vHighTop = line;
|
||
|
line = vHighTop - vLines / 2;
|
||
|
|
||
|
while (line >= vNLine) {
|
||
|
if (! (vLastLine == NOLASTLINE)) { /* Mark is past EOF? */
|
||
|
vHighTop = vLastLine - 1; /* Then set it to EOF. */
|
||
|
break;
|
||
|
}
|
||
|
if (_abort()) {
|
||
|
line = vNLine-1;
|
||
|
break;
|
||
|
}
|
||
|
fancy_percent (); /* Wait for marked line */
|
||
|
vpBlockTop = vpCur = vpTail; /* to be processed */
|
||
|
vReaderFlag = F_DOWN;
|
||
|
ResetEvent (vSemMoreData);
|
||
|
SetEvent (vSemReader);
|
||
|
WaitForSingleObject(vSemMoreData, WAITFOREVER);
|
||
|
ResetEvent(vSemMoreData);
|
||
|
}
|
||
|
|
||
|
if (line > vLastLine - vLines)
|
||
|
line = vLastLine - vLines;
|
||
|
|
||
|
if (line < 0L)
|
||
|
line = 0L;
|
||
|
|
||
|
vTopLine = line;
|
||
|
vHLBot = vHLTop = 0;
|
||
|
QuickRestore ();
|
||
|
SetUpdate (U_ALL);
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
GoToLine ()
|
||
|
{
|
||
|
char LineNum [10];
|
||
|
long line;
|
||
|
|
||
|
GetInput ("Line #.> ", LineNum, 10);
|
||
|
if (LineNum[0] == 0)
|
||
|
return;
|
||
|
line = atol (LineNum);
|
||
|
vHighTop = line;
|
||
|
vHighLen = 0;
|
||
|
|
||
|
GoToMark ();
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
SlimeTOF ()
|
||
|
{
|
||
|
char Text [10];
|
||
|
long KOff;
|
||
|
|
||
|
SyncReader ();
|
||
|
GetInput ("K Off..> ", Text, 40);
|
||
|
KOff = atol (Text) * 1024;
|
||
|
KOff -= KOff % BLOCKSIZE;
|
||
|
if (Text[0] == 0 || KOff == vpFlCur->SlimeTOF) {
|
||
|
SetEvent (vSemReader);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
vpFlCur->SlimeTOF = KOff;
|
||
|
vpFlCur->FileTime.dwLowDateTime = (unsigned)-1; /* Cause info to be invalid */
|
||
|
vpFlCur->FileTime.dwHighDateTime = (unsigned)-1; /* Cause info to be invalid */
|
||
|
FreePages (vpFlCur);
|
||
|
NextFile (0, NULL);
|
||
|
}
|