/*** List.c * */ #include #include #include #include #include #include "list.h" #include "..\he\hexedit.h" BOOL IsValidKey (PINPUT_RECORD pRecord); void DumpFileInHex (void); static char Name[] = "Ken Reneris. List Ver 1.0."; struct Block *vpHead = NULL; /* Current first block */ struct Block *vpTail = NULL; /* Current last block */ struct Block *vpCur = NULL; /* Current block for display 1st line */ /* (used by read ahead to sense) */ struct Block *vpBCache = NULL; /* 'free' blocks which can cache reads */ struct Block *vpBOther = NULL; /* (above) + for other files */ struct Block *vpBFree = NULL; /* free blocks. not valid for caching reads */ int vCntBlks; /* No of blocks currently is use by cur file*/ int vAllocBlks = 0; /* No of blocks currently alloced */ int vMaxBlks = MINBLKS; /* Max blocks allowed to alloc */ long vThreshold = MINTHRES*BLOCKSIZE; /* Min bytes before read ahead */ HANDLE vSemBrief = 0L; /* To serialize access to Linked list info */ HANDLE vSemReader = 0L; /* To wakeup reader thread when threshold */ HANDLE vSemMoreData = 0L; /* Blocker for Disp thread if ahead of read */ HANDLE vSemSync = 0L; /* Used to syncronize to sync to the reader */ USHORT vReadPriNormal; /* Normal priority for reader thread */ unsigned vReadPriBoost; /* Boosted priority for reader thread */ char vReaderFlag; /* Insructions to reader */ HANDLE vFhandle = 0; /* Current file handle */ long vCurOffset; /* Current offset in file */ char vpFname [40]; /* Current files name */ struct Flist *vpFlCur =NULL; /* Current file */ USHORT vFType; /* Current files handle type */ WIN32_FIND_DATA vFInfo; /* Current files info */ char vDate [30]; /* Printable dat of current file */ char vSearchString [50]; /* Searching for this string */ char vStatCode; /* Codes for search */ long vHighTop = -1L; /* Current topline of hightlighting */ int vHighLen; /* Current bottom line of hightlighting */ char vHLTop = 0; /* Last top line displayed as highlighted */ char vHLBot = 0; /* Last bottom line displayed as highlighed */ char vLastBar; /* Last line for thumb mark */ int vMouHandle; /* Mouse handle (for Mou Apis) */ HANDLE vhConsoleOutput; // Handle to the console char *vpOrigScreen; /* Orinal screen contents */ int vOrigSize; /* # of bytes in orignal screen */ USHORT vVioOrigRow = 0; /* Save orignal screen stuff. */ USHORT vVioOrigCol = 0; int vSetBlks = 0; /* Used to set INI value */ long vSetThres = 0L; /* Used to set INI value */ int vSetLines; /* Used to set INI value */ int vSetWidth; /* Used to set INI value */ CONSOLE_SCREEN_BUFFER_INFO vConsoleCurScrBufferInfo; CONSOLE_SCREEN_BUFFER_INFO vConsoleOrigScrBufferInfo; /* Screen controling... used to be static in ldisp.c */ char vcntScrLock = 0; /* Locked screen count */ char vSpLockFlag = 0; /* Special locked flag */ HANDLE vSemLock = 0; /* To access vcntScrLock */ char vUpdate; int vLines = 23; /* CRTs no of lines */ int vWidth = 80; /* CRTs width */ int vCurLine; /* When processing lines on CRT */ Uchar vWrap = 254; /* # of chars to wrap at */ Uchar vIndent = 0; /* # of chars dispaly is indented */ Uchar vDisTab = 8; /* # of chars per tab stop */ Uchar vIniFlag = 0; /* Various ini bits */ Uchar vrgLen [MAXLINES]; /* Last len of data on each line */ Uchar vrgNewLen[MAXLINES]; /* Temp moved to DS for speed */ char *vScrBuf; /* Ram to build screen into */ ULONG vSizeScrBuf; int vOffTop; /* Offset into data for top line */ unsigned vScrMass = 0; /* # of bytes for last screen (used for %) */ struct Block *vpBlockTop; /* Block for start of screen (dis.asm) overw*/ struct Block *vpCalcBlock; /* Block for start of screen */ long vTopLine = 0L; /* Top line on the display */ #define FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) #define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) #define HIWHITE_ON_BLUE (BACKGROUND_BLUE | FOREGROUND_WHITE | FOREGROUND_INTENSITY) WORD vAttrTitle = HIWHITE_ON_BLUE; WORD vAttrList = BACKGROUND_BLUE | FOREGROUND_WHITE; WORD vAttrHigh = BACKGROUND_WHITE | FOREGROUND_BLUE; WORD vAttrKey = HIWHITE_ON_BLUE; WORD vAttrCmd = BACKGROUND_BLUE | FOREGROUND_WHITE; WORD vAttrBar = BACKGROUND_BLUE | FOREGROUND_WHITE; WORD vSaveAttrTitle = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; WORD vSaveAttrList = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; WORD vSaveAttrHigh = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; WORD vSaveAttrKey = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; WORD vSaveAttrCmd = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; WORD vSaveAttrBar = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; char vChar; /* Scratch area */ char *vpReaderStack; /* Readers stack */ long vDirOffset; /* Direct offset to seek to */ /* table */ long vLastLine; /* Absolute last line */ long vNLine; /* Next line to process into line table */ long *vprgLineTable [MAXTPAGE]; /* Number of pages for line table */ HANDLE vStdOut; HANDLE vStdIn; char MEMERR[]= "Malloc failed. Out of memory?"; void __cdecl main ( int argc, char **argv ) { void usage (void); char *pt; DWORD dwMode; if (argc < 2) usage (); while (--argc) { ++argv; if (*argv[0] != '-' && *argv[0] != '/') { AddFileToList (*argv); continue; } pt = (*argv) + 2; if (*pt == ':') pt++; switch ((*argv)[1]) { case 'g': // Goto line # case 'G': if (!atol (pt)) usage (); vIniFlag |= I_GOTO; vHighTop = atol (pt); vHighLen = 0; break; case 's': // Search for string case 'S': vIniFlag |= I_SEARCH; strncpy (vSearchString, pt, 40); vSearchString[39] = 0; vStatCode |= S_NEXT | S_NOCASE; InitSearchReMap (); break; default: usage (); } } if ((vIniFlag & I_GOTO) && (vIniFlag & I_SEARCH)) usage (); if (!vpFlCur) usage (); while (vpFlCur->prev) vpFlCur = vpFlCur->prev; strcpy (vpFname, vpFlCur->rootname); vSemBrief = CreateEvent( NULL, MANUAL_RESET, SIGNALED,NULL ); vSemReader = CreateEvent( NULL, MANUAL_RESET, SIGNALED,NULL ); vSemMoreData = CreateEvent( NULL, MANUAL_RESET, SIGNALED,NULL ); vSemSync = CreateEvent( NULL, MANUAL_RESET, SIGNALED,NULL ); vSemLock = CreateEvent( NULL, MANUAL_RESET, SIGNALED,NULL ); if( !(vSemBrief && vSemReader &&vSemMoreData && vSemSync && vSemLock) ) { printf("Couldn't create events \n"); ExitProcess (0); // Have to put an error message here } vhConsoleOutput = CreateConsoleScreenBuffer(GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CONSOLE_TEXTMODE_BUFFER, NULL ); if( vhConsoleOutput == (HANDLE)(-1) ) { printf( "Couldn't create handle to console output \n" ); ExitProcess (0); } vStdIn = GetStdHandle( STD_INPUT_HANDLE ); GetConsoleMode( vStdIn, &dwMode ); SetConsoleMode( vStdIn, dwMode | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT ); vStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); init_list (); vUpdate = U_NMODE; if (vIniFlag & I_SEARCH) FindString (); if (vIniFlag & I_GOTO) GoToMark (); main_loop (); } void usage ( void ) { puts ("list [-s:string] [-g:line#] filename, ..."); CleanUp(); ExitProcess(0); } /*** main_loop * */ void main_loop () { int i; int ccnt = 0; char SkipCnt=0; WORD RepeatCnt=0; INPUT_RECORD InpBuffer; DWORD cEvents; BOOL bSuccess; BOOL bKeyDown = FALSE; for (; ;) { if (RepeatCnt <= 1) { if (vUpdate != U_NONE) { if (SkipCnt++ > 5) { SkipCnt = 0; SetUpdate (U_NONE); } else { cEvents = 0; bSuccess = PeekConsoleInput( vStdIn, &InpBuffer, 1, &cEvents ); if (!bSuccess || cEvents == 0) { PerformUpdate (); continue; } } } // there's either a charactor available from peek, or vUpdate is U_NONE bSuccess = ReadConsoleInput( vStdIn, &InpBuffer, 1, &cEvents ); if (InpBuffer.EventType != KEY_EVENT) { // TCHAR s[1024]; switch (InpBuffer.EventType) { #if 0 case WINDOW_BUFFER_SIZE_EVENT: sprintf (s, "WindowSz X=%d, Y=%d", InpBuffer.Event.WindowBufferSizeEvent.dwSize.X, InpBuffer.Event.WindowBufferSizeEvent.dwSize.Y ); DisLn (20, (Uchar)(vLines+1), s); break; #endif case MOUSE_EVENT: #if 0 sprintf (s, "Mouse (%d,%d), state %x, event %x", InpBuffer.Event.MouseEvent.dwMousePosition.X, InpBuffer.Event.MouseEvent.dwMousePosition.Y, InpBuffer.Event.MouseEvent.dwButtonState, InpBuffer.Event.MouseEvent.dwEventFlags ); #endif if (InpBuffer.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED) { // HiWord of ButtonState is signed int, in increments of 120 (WHEEL_DELTA). // Map each 'detent' to a 4 line scroll in the console window. // Rolling away from the user should scroll up (dLines should be negative). // Since rolling away generates a positive dwButtonState, the negative sign // makes rolling away scroll up, and rolling towards you scroll down. SHORT dLines = -(SHORT)(HIWORD(InpBuffer.Event.MouseEvent.dwButtonState)) / (WHEEL_DELTA / 4); vTopLine += dLines; // make sure to stay between line 0 and vLastLine if (vTopLine+vLines > vLastLine) vTopLine = vLastLine-vLines; if (vTopLine < 0) vTopLine = 0; SetUpdateM (U_ALL); } // DisLn (20, (Uchar)(vLines+1), s); break; default: #if 0 sprintf (s, "Unkown event %d", InpBuffer.EventType); DisLn (20, (Uchar)(vLines+1), s); #endif break; } continue; } if (!InpBuffer.Event.KeyEvent.bKeyDown) continue; // don't move on upstrokes if (!IsValidKey( &InpBuffer )) continue; RepeatCnt = InpBuffer.Event.KeyEvent.wRepeatCount; if (RepeatCnt > 20) RepeatCnt = 20; } else RepeatCnt--; // First check for a known scan code switch (InpBuffer.Event.KeyEvent.wVirtualKeyCode) { case 0x21: /* PgUp */ if (InpBuffer.Event.KeyEvent.dwControlKeyState & // shift up SHIFT_PRESSED ) { HPgUp (); } else if (InpBuffer.Event.KeyEvent.dwControlKeyState & // ctrl up ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED ) ) { if (NextFile (-1, NULL)) { vStatCode |= S_UPDATE; SetUpdate (U_ALL); } } else { if (vTopLine != 0L) { vTopLine -= vLines-1; if (vTopLine < 0L) vTopLine = 0L; SetUpdateM (U_ALL); } } continue; case 0x26: /* Up */ if (InpBuffer.Event.KeyEvent.dwControlKeyState & // shift or ctrl up ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED | SHIFT_PRESSED ) ) { HUp (); } else { // Up if (vTopLine != 0L) { vTopLine--; SetUpdateM (U_ALL); } } continue; case 0x22: /* PgDn */ if (InpBuffer.Event.KeyEvent.dwControlKeyState & // shift down SHIFT_PRESSED ) { HPgDn (); } else if (InpBuffer.Event.KeyEvent.dwControlKeyState & // next file ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED ) ) { if (NextFile (+1, NULL)) { vStatCode |= S_UPDATE; SetUpdate (U_ALL); } } else { // PgDn if (vTopLine+vLines < vLastLine) { vTopLine += vLines-1; if (vTopLine+vLines > vLastLine) vTopLine = vLastLine - vLines; SetUpdateM (U_ALL); } } continue; case 0x28: /* Down */ if (InpBuffer.Event.KeyEvent.dwControlKeyState & // shift or ctrl down ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED | SHIFT_PRESSED ) ) { HDn (); } else { // Down if (vTopLine+vLines < vLastLine) { vTopLine++; SetUpdateM (U_ALL); } } continue; case 0x25: /* Left */ if (vIndent == 0) continue; vIndent = (Uchar)(vIndent < vDisTab ? 0 : vIndent - vDisTab); SetUpdateM (U_ALL); continue; case 0x27: /* Right */ if (vIndent >= (Uchar)(254-vWidth)) continue; vIndent += vDisTab; SetUpdateM (U_ALL); continue; case 0x24: /* HOME */ if (InpBuffer.Event.KeyEvent.dwControlKeyState & // shift or ctrl home ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED | SHIFT_PRESSED ) ) { HSUp (); } else { if (vTopLine != 0L) { QuickHome (); SetUpdate (U_ALL); } } continue; case 0x23: /* END */ if (InpBuffer.Event.KeyEvent.dwControlKeyState & // shift or ctrl end ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED | SHIFT_PRESSED ) ) { HSDn (); } else { if (vTopLine+vLines < vLastLine) { QuickEnd (); SetUpdate (U_ALL); } } continue; case 0x72: /* F3 */ FindString (); SetUpdate (U_ALL); continue; case 0x73: /* F4 */ vStatCode = (char)((vStatCode^S_MFILE) | S_UPDATE); vDate[ST_SEARCH] = (char)(vStatCode & S_MFILE ? '*' : ' '); SetUpdate (U_HEAD); continue; case 69: if (InpBuffer.Event.KeyEvent.dwControlKeyState & // ALT-E ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) ) { i = vLines <= 41 ? 25 : 43; if (set_mode (i, 0, 0)) SetUpdate (U_NMODE); } continue; case 86: // ALT-V if (InpBuffer.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) ) { i = vLines >= 48 ? 25 : 60; if (set_mode (i, 0, 0)) { SetUpdate (U_NMODE); continue; } if (i == 60) if (set_mode (50, 0, 0)) SetUpdate (U_NMODE); } continue; case 0x70: /* F1 */ ShowHelp (); SetUpdate (U_NMODE); continue; case 24: /* Offset */ if (!(vIniFlag & I_SLIME)) continue; SlimeTOF (); SetUpdate (U_ALL); continue; case 0x77: // F8 case 0x1b: // ESC case 0x51: // Q or q CleanUp(); ExitProcess(0); } // Now check for a known char code... switch (InpBuffer.Event.KeyEvent.uChar.AsciiChar) { case '?': ShowHelp (); SetUpdate (U_NMODE); continue; case '/': vStatCode = (char)((vStatCode & ~S_NOCASE) | S_NEXT); GetSearchString (); FindString (); continue; case '\\': vStatCode |= S_NEXT | S_NOCASE; GetSearchString (); FindString (); continue; case 'n': vStatCode = (char)((vStatCode & ~S_PREV) | S_NEXT); FindString (); continue; case 'N': vStatCode = (char)((vStatCode & ~S_NEXT) | S_PREV); FindString (); continue; case 'c': case 'C': /* Clear marked line */ UpdateHighClear (); continue; case 'j': case 'J': /* Jump to marked line */ GoToMark (); continue; case 'g': case 'G': /* Goto line # */ GoToLine (); SetUpdate (U_ALL); continue; case 'm': /* Mark line or Mono */ case 'M': if (InpBuffer.Event.KeyEvent.dwControlKeyState & // ALT-M ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) ) { i = set_mode (vSetLines, vSetWidth, 1); if (!i) i = set_mode (0, 0, 1); if (!i) i = set_mode (25, 80, 1); if (i) SetUpdate (U_NMODE); } else { MarkSpot (); } continue; case 'p': /* Paste buffer to file */ case 'P': FileHighLighted (); continue; case 'f': /* get a new file */ case 'F': if (GetNewFile ()) if (NextFile (+1, NULL)) SetUpdate (U_ALL); continue; case 'h': /* hexedit */ case 'H': DumpFileInHex(); SetUpdate (U_NMODE); continue; case 'w': /* WRAP */ case 'W': ToggleWrap (); SetUpdate (U_ALL); continue; case 'l': /* REFRESH */ case 'L': /* REFRESH */ if (InpBuffer.Event.KeyEvent.dwControlKeyState & // ctrl L ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED ) ) { SetUpdate (U_NMODE); } continue; case '\r': /* ENTER*/ SetUpdate (U_HEAD); continue; default: continue; } } /* Forever loop */ } void SetUpdate( int i ) { while (vUpdate>(char)i) PerformUpdate (); vUpdate=(char)i; } void PerformUpdate ( ) { if (vUpdate == U_NONE) return; if (vSpLockFlag == 0) { vSpLockFlag = 1; ScrLock (1); } switch (vUpdate) { case U_NMODE: ClearScr (); DisLn (0, 0, vpFname); DrawBar (); break; case U_ALL: Update_display (); break; case U_HEAD: Update_head (); break; case U_CLEAR: SpScrUnLock (); break; } vUpdate --; } NTSTATUS fncRead(HANDLE, DWORD, DWORD, char *, ULONG *); NTSTATUS fncWrite(HANDLE, DWORD, DWORD, char *, ULONG *); void DumpFileInHex( void ) { struct HexEditParm ei; ULONG CurLine; SyncReader (); memset ((char *) &ei, 0, sizeof (ei)); ei.handle = CreateFile( vpFlCur->fname, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if (ei.handle == INVALID_HANDLE_VALUE) { ei.handle = CreateFile( vpFlCur->fname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); } if (ei.handle == INVALID_HANDLE_VALUE) { SetEvent (vSemReader); return ; } // // Save current settings for possible restore // vpFlCur->Wrap = vWrap; vpFlCur->HighTop = vHighTop; vpFlCur->HighLen = vHighLen; vpFlCur->TopLine = vTopLine; vpFlCur->Loffset = GetLoffset(); vpFlCur->LastLine = vLastLine; vpFlCur->NLine = vNLine; memcpy (vpFlCur->prgLineTable, vprgLineTable, sizeof (long *) * MAXTPAGE); vFInfo.nFileSizeLow = 0; setattr2 (0, 0, vWidth, (char)vAttrTitle); // // Setup for HexEdit call // if (vHighTop >= 0) { // If highlighted area, CurLine = vHighTop; // use that for the HexEdit if (vHighLen < 0) // location CurLine += vHighLen; } else { CurLine = vTopLine; } ei.ename = vpFname; ei.ioalign = 1; ei.flag = FHE_VERIFYONCE; ei.read = fncRead; ei.write = fncWrite; ei.start = vprgLineTable[CurLine/PLINES][CurLine%PLINES]; ei.totlen = SetFilePointer (ei.handle, 0, NULL, FILE_END); ei.Console = vhConsoleOutput; // our console handle ei.AttrNorm = vAttrList; ei.AttrHigh = vAttrTitle; ei.AttrReverse = vAttrHigh; HexEdit (&ei); CloseHandle (ei.handle); // // HexEdit is done, let reader and return to listing // vReaderFlag = F_NEXT; // re-open current file // (in case it was editted) SetEvent (vSemReader); WaitForSingleObject(vSemMoreData, WAITFOREVER); ResetEvent(vSemMoreData); QuickRestore (); /* Get to the old location */ } int NextFile ( int dir, struct Flist *pNewFile) { struct Flist *vpFLCur; long *pLine; vpFLCur = vpFlCur; if (pNewFile == NULL) { if (dir < 0) { if (vpFlCur->prev == NULL) { beep (); return (0); } vpFlCur = vpFlCur->prev; } else if (dir > 0) { if (vpFlCur->next == NULL) { beep (); return (0); } vpFlCur = vpFlCur->next; } } else vpFlCur = pNewFile; SyncReader (); /* * Remove current file from list, if open error * occured and we are moving off of it. */ if (vFInfo.nFileSizeLow == -1L && vpFLCur != vpFlCur) { if (vpFLCur->prev) vpFLCur->prev->next = vpFLCur->next; if (vpFLCur->next) vpFLCur->next->prev = vpFLCur->prev; FreePages (vpFLCur); free ((char*) vpFLCur->fname); free ((char*) vpFLCur->rootname); free ((char*) vpFLCur); } else { /* * Else, save current status for possible restore */ vpFLCur->Wrap = vWrap; vpFLCur->HighTop = vHighTop; vpFLCur->HighLen = vHighLen; vpFLCur->TopLine = vTopLine; vpFLCur->Loffset = GetLoffset(); vpFLCur->LastLine = vLastLine; vpFLCur->NLine = vNLine; memcpy (vpFLCur->prgLineTable, vprgLineTable, sizeof (long *) * MAXTPAGE); if (vLastLine == NOLASTLINE) { pLine = vprgLineTable [vNLine/PLINES] + vNLine % PLINES; } } vFInfo.nFileSizeLow = 0; setattr2 (0, 0, vWidth, (char)vAttrTitle); vHighTop = -1L; UpdateHighClear (); vHighTop = vpFlCur->HighTop; vHighLen = vpFlCur->HighLen; strcpy (vpFname, vpFlCur->rootname); DisLn (0, 0, vpFname); vReaderFlag = F_NEXT; SetEvent (vSemReader); WaitForSingleObject(vSemMoreData, WAITFOREVER); ResetEvent(vSemMoreData); if (pNewFile == NULL) QuickRestore (); /* Get to the old location */ return (1); } void ToggleWrap( ) { SyncReader (); vWrap = (Uchar)(vWrap == (Uchar)(vWidth - 1) ? 254 : vWidth - 1); 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); } /*** QuickHome - Deciede which HOME method is better. * * Roll que backwards or reset it. * */ void QuickHome () { vTopLine = 0L; /* Line we're after */ if (vpHead->offset >= BLOCKSIZE * 5) /* Reset is fastest */ QuickRestore (); /* Else Read backwards */ vpCur = vpHead; } void QuickEnd () { vTopLine = 1L; while (vLastLine == NOLASTLINE) { if (_abort()) { vTopLine = vNLine - 1; return ; } fancy_percent (); vpBlockTop = vpCur = vpTail; vReaderFlag = F_DOWN; ResetEvent (vSemMoreData); SetEvent (vSemReader); WaitForSingleObject(vSemMoreData, WAITFOREVER); ResetEvent(vSemMoreData); } vTopLine = vLastLine - vLines; if (vTopLine < 0L) vTopLine = 0L; QuickRestore (); } void QuickRestore () { long l; long indx1 = vTopLine/PLINES; long indx2 = vTopLine%PLINES; SyncReader (); if(indx1 < MAXTPAGE) { l = vprgLineTable[indx1][indx2]; } else { puts("Sorry, This file is too big for LIST to handle. MAXTPAGE limit exceeded\n"); CleanUp(); ExitProcess(0); } if ((l >= vpHead->offset) && (l <= vpTail->offset + BLOCKSIZE)) { vReaderFlag = F_CHECK; /* Jump location is alread in */ /* memory. */ SetEvent (vSemReader); return ; } /* Command read for direct placement */ vDirOffset = (long) l - l % ((long)BLOCKSIZE); vReaderFlag = F_DIRECT; SetEvent (vSemReader); WaitForSingleObject(vSemMoreData, WAITFOREVER); ResetEvent(vSemMoreData); } /*** InfoRead - return on/off depending if screen area is in memory * * Also sets some external value to prepair for the screens printing * * Should be modified to be smarter about one line movements. * */ int InfoReady( void ) { struct Block *pBlock; LONG *pLine; long foffset, boffset; int index, i, j; /* * Check that first line has been calced */ if (vTopLine >= vNLine) { if (vTopLine+vLines > vLastLine) /* BUGFIX. TopLine can */ vTopLine = vLastLine - vLines; /* get past EOF. */ vReaderFlag = F_DOWN; return (0); } pLine = vprgLineTable [(int)vTopLine / PLINES]; index = (int)(vTopLine % PLINES); foffset = *(pLine+=index); /* * Check that last line has been calced */ if (vTopLine + (i = vLines) > vLastLine) { i = (int)(vLastLine - vTopLine + 1); for (j=i; j < vLines; j++) /* Clear ending len */ vrgNewLen[j] = 0; } if (vTopLine + i > vNLine) { vReaderFlag = F_DOWN; return (0); } /* * Put this loop in assembler.. For more speed * boffset = calc_lens (foffset, i, pLine, index); */ boffset = foffset; for (j=0; j < i; j++) { /* Calc new line len*/ pLine++; if (++index >= PLINES) { index = 0; pLine = vprgLineTable [vTopLine / PLINES + 1]; } boffset += (long)((vrgNewLen[j] = (Uchar)(*pLine - boffset))); } vScrMass = (unsigned)(boffset - foffset); /* * Check for both ends of display in memory */ pBlock = vpCur; if (pBlock->offset <= foffset) { while (pBlock->offset + BLOCKSIZE <= foffset) if ( (pBlock = pBlock->next) == NULL) { vReaderFlag = F_DOWN; return (0); } vOffTop = (int)(foffset - pBlock->offset); vpBlockTop = vpCalcBlock = pBlock; while (pBlock->offset + BLOCKSIZE <= boffset) if ( (pBlock = pBlock->next) == NULL) { vReaderFlag = F_DOWN; return (0); } if (vpCur != pBlock) { vpCur = pBlock; vReaderFlag = F_CHECK; SetEvent (vSemReader); } return (1); } else { while (pBlock->offset > foffset) if ( (pBlock = pBlock->prev) == NULL) { vReaderFlag = F_UP; return (0); } vOffTop = (int)(foffset - pBlock->offset); vpBlockTop = vpCalcBlock = pBlock; while (pBlock->offset + BLOCKSIZE <= boffset) if ( (pBlock = pBlock->next) == NULL) { vReaderFlag = F_DOWN; return (0); } if (vpCur != pBlock) { vpCur = pBlock; vReaderFlag = F_CHECK; SetEvent (vSemReader); } return (1); } }