windows-nt/Source/XPSP1/NT/sdktools/list/lsearch.c
2020-09-26 16:20:57 +08:00

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);
}