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