1061 lines
34 KiB
C
1061 lines
34 KiB
C
|
/*** List.c
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <malloc.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <windows.h>
|
||
|
#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 */
|
||
|
DWORD vFSize; /* Current file size */
|
||
|
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 --;
|
||
|
}
|
||
|
|
||
|
|
||
|
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);
|
||
|
|
||
|
vFSize = 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 (vFSize == -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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vFSize = 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);
|
||
|
}
|
||
|
}
|