#include <windows.h>
#include <stdio.h>
#include <time.h>

#include "resource.h"

HDC hDC, hCompatibleDC;
HFONT hf;
HANDLE hl_bmp;
PAINTSTRUCT PaintStruct;
HWND hwnd, hWnd;// This is the handle for our window
MSG messages;// Here messages to the application are saved
WNDCLASSEX wincl;// Data structure for the windowclass
RECT Rect;
COLORREF g_rgbBackground=RGB (0, 0, 0);
COLORREF g_rgbText=RGB (255, 255, 255);
COLORREF g_rgbBackgroundHL=RGB (170, 170, 255);
COLORREF g_rgbTextHL=RGB (25, 25, 25);
COLORREF g_rgbBackgroundSeek=RGB (242, 170, 25);
COLORREF g_rgbBackgroundHLnSeek=RGB (170, 100, 255);
COLORREF g_rgbHLnSeek=RGB (0, 0, 0);
COLORREF g_rgbWordSeek=RGB (255, 0, 0);
COLORREF g_rgbWordHLnSeek=RGB (255, 255, 255);
COLORREF g_rgbBackgroundCapture=RGB (0, 155, 0);
FILE *lv_file;

char seek [16];

char g_title [100];

int lv_range0=32;
int lv_range1=1024*8;
int lv_range2=512;
int lv_range=lv_range2;
#define lv_range_mx 1024*8
unsigned long lv_size;
int lv_lines0=32;
int lv_lines=lv_lines0;
int lv_lines1=128;
int lv_hilight=0;
int lv_cols0=89;
int lv_cols=lv_cols0;
int lv_cols1=512;
#define lv_cols_mx 512+1
char lv_txt [128] [1024*8];
int lv_shift=0;
int lv_len [128];
unsigned long lv_end;
unsigned long lv_pos=0;
unsigned long lv_pos1=0;
unsigned long lv_pos1up=0;
unsigned long lv_pos30=0;
int lv_mode=0;
bool lv_cls=false, lv_init=false, lv_over=false, init_off=false, no_rest=false;

bool lv_capture=false, seek_once=false, seek_hl=false;
const unsigned int TIMER_CAPTURE=10;

int mx_len=2100000000, lv_sp;
bool too_long=false;

bool ctrl_key=false, shift_key=false, shift_key2=false, shift_key3=true;

int g_l=0;

char path [_MAX_PATH], path2 [_MAX_PATH], path3 [_MAX_PATH];
int path2_l=0, path3_l;

int lv_max=0, lv_h0=619, lv_h1=644, lv_h=644, lv_w0=900, lv_w=906;
HINSTANCE gThisInstance;
int gFunsterStil;

int xoff=3, yoff=22;

int sx=(LONG)::GetSystemMetrics (SM_CXFULLSCREEN);
int sy=(LONG)::GetSystemMetrics (SM_CYFULLSCREEN);
int wx=(int)((sx-(lv_w-4))/2);
int wy=(int)((sy-(lv_h+4))/2);

// Make the class name into a global variable
char szClassName []="WindowsApp";

char AppPath [_MAX_PATH];
char RootPath [_MAX_PATH];
int ap_l=0;

int down_off_pgdown_c,down_off_pgup_c;

int min_r_left, min_r_top;


bool is_seek (int row)
{
 seek_hl=false;
 int i, i2, c, sl_seek=strlen (seek);

 if (sl_seek>0 && lv_len [row]-2-sl_seek+1>0)
 {
  for (i=0; i<lv_len [row]-2-sl_seek+1; i++)
  {
   c=0;
   for (i2=0; i2<sl_seek; i2++)
   {
    if (lv_txt [row] [i+i2]!=seek [i2])
     break;
    else
     c++;
   }
   if (c==sl_seek)
   {
    seek_hl=true;
    seek_once=true;
    break;
   }
  }
 }

 if (seek_hl)
  return true;
}

bool captured=false;
void capture ()
{
 FILE *file;
 int i, l;
 char txt [lv_range_mx];
 memset (txt, 0, lv_range_mx);
 unsigned long f_size=0;

 seek_once=false;
 for (i=0; i<lv_lines; i++)
  is_seek (i);

 char path [_MAX_PATH];
 memset (path, 0, _MAX_PATH);
 memcpy (path, path3, path3_l);
 strcat (path, "LogViewer.txt");
 if (captured==false)
 {
  file=fopen (path, "r");
  if (file!=NULL)
  {
   fseek (file, 0, SEEK_END);// seek to end of file
   f_size=ftell (file);// get current file pointer
   fclose (file);
  }
 }

 file=fopen (path, "a");
 if (file!=NULL)
 {
  if (captured==false)
  {
   char cap [200];
   memset (cap, 0, 200);

   strcat (cap, g_title);
   strcat (cap, " [");

   char dateStr [9];
   char timeStr [9];
   _strdate (dateStr);
   strcat (cap, dateStr);
   strcat (cap, " ");
   _strtime (timeStr);
   strcat (cap, timeStr);

   strcat (cap, "]");

   if (f_size!=0)
   {
    fputc ('\n', file);
    fputc ('\n', file);
    fputc ('\n', file);
   }
   fputs (cap, file);
   fputc ('\n', file);
   fputc ('\n', file);
  }

  if (captured==true)
   fputc ('\n', file); 

  for (i=0; i<lv_lines; i++)
  {
   if ((lv_hilight!=0 && lv_hilight==i) || (seek_once && is_seek (i)) || (lv_hilight==0 && !seek_once))
   {
    memset (txt, 0, lv_range);
    l=lv_len [i]-2;
    if (l<0)
     l=0;
    memcpy (txt, lv_txt [i], l);
    fputs (txt, file);
    fputc ('\n', file);
   }
  }

  fclose (file);

  captured=true;

  RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
 }
}

void save_conf()
{
 FILE *file;
 int i;
 char conf [1024];
 memset (conf, 0, 1024);

 if (lv_max==0)
 {
  GetWindowRect(hwnd, &Rect);
  min_r_left=Rect.left;
  min_r_top=Rect.top;
 }

 int snap0 [10];
 char snap [39];
 memset (snap0, 0, 10);
 memset (snap, 32, 39);
 if (lv_file!=NULL && lv_size>0)
 {
  unsigned long i0=lv_pos-2, i1=lv_pos+2;
  int c=0;
  if ((int)i0<0)
   i0=0;
  if (i1>lv_size)
   i1=lv_size;
  while (c<5)
  {
   fseek (lv_file, i0, SEEK_SET);
   snap0 [c]=fgetc (lv_file);
   if (i0<i1)
    i0++;
   c++;
  }

  while (c<10)
  {
   i0=lv_pos/20*c+10;
   if (i0<0)
    i0=0;
   if (i0>lv_size)
    i0=lv_size;
   fseek (lv_file, i0, SEEK_SET);
   snap0 [c]=fgetc (lv_file);
   c++;
  }


  sprintf (snap, "%d %d %d %d %d %d %d %d %d %d ", snap0 [0], snap0 [1], snap0 [2], snap0 [3], snap0 [4], snap0 [5], snap0 [6], snap0 [7], snap0 [8], snap0 [9]);
 }

 sprintf (conf, "%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n%s\n%s\n%s\n", lv_range, min_r_left, min_r_top, (lv_hilight!=0 ? 1 : 0), lv_max, lv_pos, lv_shift, lv_size, path2, snap, seek);

 char path [_MAX_PATH];
 memset (path, 0, _MAX_PATH);
 memcpy (path, AppPath, ap_l);
 strcat (path, "data\\config.txt");

 file=fopen (path, "w");
 if (file!=NULL)
 {
  for (i=0; i<1024; i++)
  {
   if (conf [i]!=0)
    fputc (conf[i], file);
  }

  fclose (file);
 }

 if (lv_file!=NULL)
  fclose (lv_file);
}

void row_out (int row, char txt [lv_cols_mx])
{
 int i, i2, c, sl_seek=strlen (seek);

 SetBkMode (hCompatibleDC, 2);

 is_seek (row);

 if (lv_hilight!=0 && row==lv_hilight)
 {
  SetTextColor (hCompatibleDC, g_rgbTextHL);

  if (lv_capture)
   SetBkColor (hCompatibleDC, g_rgbBackgroundCapture);
  else if (seek_hl)
   SetBkColor (hCompatibleDC, g_rgbBackgroundHLnSeek);
  else
   SetBkColor (hCompatibleDC, g_rgbBackgroundHL);
 }
 else
 {
  if (seek_hl)
  {
   SetTextColor (hCompatibleDC, g_rgbHLnSeek);

   if (lv_capture)
    SetBkColor (hCompatibleDC, g_rgbBackgroundCapture);
   else
    SetBkColor (hCompatibleDC, g_rgbBackgroundSeek);
  }
  else
  {
   SetTextColor (hCompatibleDC, g_rgbText);

   if (lv_capture && !seek_once && lv_hilight==0)
    SetBkColor (hCompatibleDC, g_rgbBackgroundCapture);
   else
    SetBkColor (hCompatibleDC, g_rgbBackground);
  }
 }

 GetClientRect (hwnd, &Rect);
 SetRect (&Rect, Rect.left, 0, Rect.right, 18);
 DrawText (hCompatibleDC, txt, lv_cols, &Rect, DT_SINGLELINE | DT_CENTER | DT_TOP | DT_NOPREFIX);

 if (seek_hl)
 {
  int txt_l=strlen (txt);
  char txt2 [lv_cols_mx];
  memset (txt2, 32, lv_cols_mx);

  for (i=0; i<txt_l; i++)
  {
   c=0;
   for (i2=0; i2<sl_seek; i2++)
   {
    if (i+lv_shift+i2>=lv_len [row]-2)
     break;
    else if (lv_txt [row] [i+lv_shift+i2]!=seek [i2])
     break;
    else
     c++;
   }
   if (c==sl_seek)
   {
    for (i2=0; i2<sl_seek; i2++)
     txt2 [i+i2]=txt [i+i2];
   }
  }

  if (lv_hilight!=0 && row==lv_hilight)
   SetTextColor (hCompatibleDC, g_rgbWordHLnSeek);
  else
   SetTextColor (hCompatibleDC, g_rgbWordSeek);

  SetBkMode (hCompatibleDC, 0);
  DrawText (hCompatibleDC, txt2, lv_cols, &Rect, DT_SINGLELINE | DT_CENTER | DT_TOP | DT_NOPREFIX);
 }

 GetClientRect (hwnd, &Rect);
 BitBlt (hDC, Rect.left, Rect.top+row*18+2, Rect.right, 18, hCompatibleDC, 0, 0, SRCCOPY);
}

void quick_view ()
{
 int i, i2, c=0, l, l2;
 long pos=lv_pos, pos2=0;
 char txt [lv_range_mx], txt2 [lv_range_mx];
 bool n;

 if (lv_file!=NULL && lv_size>0)
 {
  i=0;
  lv_end=lv_cols;
  g_l=0;

  while (i<lv_lines)
  {
   c++;

   if (c>lv_range)
    i=lv_lines;

   memset (txt2, 0, lv_range_mx);

   fseek (lv_file, pos, SEEK_SET);
   fgets (txt2, lv_range, lv_file);

   pos2=ftell (lv_file)+1;

   if (pos+lv_range>=lv_size && (pos2-pos)<2)
   {
    if (lv_mode==2)
     pos2=lv_size;
   }

   if (lv_mode==2)
   {
    if ((pos2-1)>=lv_pos1up)
    {
     lv_pos=pos;
     break;
    }
   }
   else
   {
    l=0;
    memset (txt, ' ', lv_range_mx);
    for (i2=0; i2<lv_range; i2++)
    {
     l++;
     if (txt2 [i2]>31 || txt2 [i2]<0)
      txt [l-1]=txt2 [i2];
     else
      txt [l-1]=' ';

     if (txt2 [i2]==10 || txt2 [i2]==13 || pos+i2>=lv_size)// \r & \n
      break;
    }
    l+=1;
    g_l+=l;
   }

   pos=pos2-1;

   if (lv_mode==0 || lv_mode==1)
   {
    if (i==0)
     lv_pos1=pos;
    else if (i==(lv_lines-1))
     lv_pos30=pos;
   }

   if (lv_mode!=2)
   {
    l2=l-2;
    if (l2<0)
     l2=0;
    memcpy (lv_txt [i], txt, l2);
    lv_len [i]=l;
    if ((l-2)>lv_end)
     lv_end=l-2;

    i++;

    if (pos2>lv_size)
    {
     lv_over=true;
     i=lv_lines;
     lv_pos30=lv_size;
    }
    else
     lv_over=false;
   }
  }
 }
}

void row (int i)
{
 int i2;
 char txt3 [lv_cols_mx];
 memset (txt3, 0, lv_cols_mx);

 if (lv_shift!=0)
 {
  for (i2=0; i2<lv_cols; i2++)
  {
   if ((lv_shift+i2)>lv_len [i]-3)
    txt3 [i2]=' ';
   else
   {
    txt3 [i2]=lv_txt [i] [lv_shift+i2];

    if (txt3 [i2]<32 && txt3 [i2]>-1)
     txt3 [i2]=32;
   }
  }
 }
 else
 {
  for (i2=0; i2<lv_cols; i2++)
  {
   if (i2>lv_len [i]-3)
    txt3 [i2]=' ';
   else
   {
    txt3 [i2]=lv_txt [i] [i2];

    if (txt3 [i2]<32 && txt3 [i2]>-1)
     txt3 [i2]=32;
   }
  }
 }

 row_out (i, txt3);
}

void high_light ()
{
 if (lv_hilight==0)
  lv_hilight=int (lv_lines/2);
 else
  lv_hilight=0;
}

void hl_out ()
{
 int t=lv_hilight;

 hDC=GetDC (hwnd);

 hCompatibleDC=CreateCompatibleDC (hDC);
 SelectObject (hCompatibleDC, hf);
 GetClientRect (hwnd, &Rect);
 HBITMAP hbm=CreateCompatibleBitmap (hDC, Rect.right, 18);
 HBITMAP holdBM=(HBITMAP)SelectObject (hCompatibleDC, hbm);

 high_light ();

 if (lv_hilight>0)
  row (lv_hilight);
 else
  row (t);

 DeleteObject (hbm);
 DeleteDC (hCompatibleDC);

 ReleaseDC (hwnd, hDC);
}

void paint ()
{
 hDC=BeginPaint (hwnd, &PaintStruct);
 int i, i2, c;
 char txt3 [lv_cols_mx];

 if (lv_cls)
 {
  HBRUSH hLinePen=CreateSolidBrush (g_rgbBackground);
  (HBRUSH)SelectObject (hDC, hLinePen);
  GetClientRect (hwnd, &Rect);
  Rectangle (hDC, 0, 0, Rect.right, Rect.bottom);
  DeleteObject (hLinePen);
  lv_cls=false;
 }

 hCompatibleDC=CreateCompatibleDC (hDC);
 SelectObject (hCompatibleDC, hf);
 GetClientRect (hwnd, &Rect);
 HBITMAP hbm=CreateCompatibleBitmap (hDC, Rect.right, 18);
 HBITMAP holdBM=(HBITMAP)SelectObject (hCompatibleDC, hbm);

 if (lv_mode!=3)
 {
  quick_view ();
  lv_mode=3;
 }

 for (i=0; i<lv_lines; i++)
  row (i);

 SetTextColor (hCompatibleDC, g_rgbText);

 char txt0 [4];
 memset (txt0, 0, 3);
 char txt1 [4]={' ',' ',' ',' '};

 char txt2_0 [4];
 memset (txt2_0, 0, 3);
 char txt2_1 [4];

 char txt_sp [8];
 memset (txt_sp, 0, 8);

 char txt [lv_cols_mx];
 memset (txt, 0, lv_cols_mx);

 
 int per1, per2;

 if (lv_pos30>=lv_size || lv_size==0)
  per1=100;
 else
 {
  unsigned long t_1p=lv_size/100;
  per1=0;
  for (i=1; i<=100; i++)
  {
   if ((lv_pos+g_l)>=t_1p*i)
    per1=i;
   else
    break;
  }
 }

 sprintf (txt0, "%d", per1);

 if (per1<10)
  txt1 [2]=txt0 [0];
 else if (per1<100)
 {
  txt1 [1]=txt0 [0];
  txt1 [2]=txt0 [1];
 }
 else
 {
  txt1 [0]=txt0 [0];
  txt1 [1]=txt0 [1];
  txt1 [2]=txt0 [2];
 }

 if (lv_end>lv_cols)
  per2=(lv_shift+lv_cols)*100/lv_end;
 else
  per2=100;

 if (per2>100)
  per2=100;

 sprintf (txt2_0, "%d", per2);

 c=0;
 for (i=0; i<3; i++)
 {
  if (int(txt2_0 [2-i])>0)
   c++;
  else
   txt2_1 [i]=' ';
 }
 for (i=0; i<c; i++)
  txt2_1 [3-c+i]=txt2_0 [i];

 if (too_long)
  sprintf (txt_sp, " (%d%c)", lv_sp, 37);

 for (i=0; i<lv_cols1; i++)
 {
  if (i==0)
   txt [i]=' ';
  else if (i<4)
   txt [i]=txt1 [i-1];
  else if (i==4)
   txt [i]='%';
  else if (i>5 && i<9)
   txt [i]=txt2_1 [i-6];
  else if (i==9)
   txt [i]='%';
  else if (i>9 && i<10+strlen (txt_sp))
   txt [i]=txt_sp [i-10];
  else
   txt [i]=' ';
 }

 GetClientRect (hwnd, &Rect);
 SetBkMode (hCompatibleDC, 0);

 HBRUSH hLinePen=CreateSolidBrush (g_rgbBackground);
 (HBRUSH)SelectObject (hCompatibleDC, hLinePen);
 Rectangle (hCompatibleDC, 0, 0, Rect.right, 18);
 DeleteObject (hLinePen);

 int color=15;
 for (i=0; i<18; i++)
 {
  if (i<9)
   color+=5;
  else if (i>9)
   color-=5;
  HPEN hLinePen=CreatePen (PS_SOLID, 1, RGB (color*2, color, 0));
  SelectObject (hCompatibleDC, hLinePen);
  MoveToEx (hCompatibleDC, Rect.left+4, i, NULL);
  LineTo (hCompatibleDC, Rect.right-4, i);
  DeleteObject (hLinePen);
 }

 char txt4_1 [12]={'М','а','р','к','и','ч','е','в',' ','Д','.'};
 char txt4_2 [12]={'2','0','1','1','-','1','7'};

 GetClientRect (hwnd, &Rect);
 SetRect (&Rect, Rect.right-225, -1, Rect.right-4, 18);
 DrawText (hCompatibleDC, txt4_1, -1, &Rect, DT_SINGLELINE | DT_LEFT | DT_TOP | DT_NOPREFIX);

 GetClientRect (hwnd, &Rect);
 SetRect (&Rect, Rect.right-105, 0, Rect.right-4, 18);
 DrawText (hCompatibleDC, txt4_2, -1, &Rect, DT_SINGLELINE | DT_LEFT | DT_TOP | DT_NOPREFIX);

 GetClientRect (hwnd, &Rect);
 SetRect (&Rect, Rect.left+4, 0, Rect.right-4, 18);
 DrawText (hCompatibleDC, txt, -1, &Rect, DT_SINGLELINE | DT_LEFT | DT_TOP | DT_NOPREFIX);

 char st [18];
 sprintf (st, "%s|", seek);

 GetClientRect (hwnd, &Rect);
 if (too_long)
  SetRect (&Rect, 4, -1, Rect.right-122+56, 18);
 else
  SetRect (&Rect, 4, -1, Rect.right-122, 18);
 DrawText (hCompatibleDC, st, -1, &Rect, DT_SINGLELINE | DT_CENTER | DT_TOP | DT_NOPREFIX);

 GetClientRect (hwnd, &Rect);
 BitBlt (hDC, Rect.left, Rect.bottom-4-18, Rect.right, 18, hCompatibleDC, 0, 0, SRCCOPY);

 DeleteObject (hbm);
 DeleteDC (hCompatibleDC);

 EndPaint (hwnd, &PaintStruct);
}

bool view0=false;

void view_down()
{
 if (lv_pos30>=lv_size)
  return;

 lv_pos=lv_pos1;
 lv_mode=1;
 if (view0==false)
  RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
}

void view_up()
{
 if (lv_pos==0)
  return;

 int i=0;
 lv_mode=2;
 lv_pos1up=lv_pos;
 unsigned long t_lv_pos;

 unsigned long t_lv_range=lv_range;
 bool b_lv_range=false;

 for (i=0; i<2; i++)
 {
  if (lv_pos<=t_lv_range && b_lv_range==false)
  {
   t_lv_range=lv_pos;
   b_lv_range=true;
  }
  else if (b_lv_range==true)
  {
   lv_pos=0;
   lv_mode=1;
   quick_view ();
   lv_mode=3;

   RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);

   break;
  }

  t_lv_pos=lv_pos-t_lv_range;

  if (i==1)
   t_lv_pos-=1;
  lv_pos=t_lv_pos;
  quick_view ();
  if (lv_pos!=t_lv_pos)
  {
   lv_mode=1;
   if (view0==false)
    RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);

   break;
  }
  else
  {
   lv_pos=lv_pos1up;

   if (i==1)
    lv_mode=3;
  }
 }
}

void view_right()
{
 if (lv_shift<lv_end-lv_cols)
 {
  lv_shift++;
  lv_mode=3;
  RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
 }
}

void view_left()
{
 if (lv_shift>0)
 {
  lv_shift--;
  lv_mode=3;
  RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
 }
}

void view_end ()
{
 bool rw=true;

 if (lv_hilight>0)
 {
  if (lv_shift==lv_len [lv_hilight]-2-lv_cols)
   rw=false;
  else if ((lv_len [lv_hilight]-2)>lv_cols)
   lv_shift=lv_len [lv_hilight]-2-lv_cols;
  else if (lv_shift!=0)
   lv_shift=0;
  else
   rw=false;
 }
 else if (lv_end>lv_cols && lv_shift!=lv_end-lv_cols)
  lv_shift=lv_end-lv_cols;
 else
  rw=false;

 if (rw==true)
 {
  lv_mode=3;
  RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
 }
}

void view_home ()
{
 if (lv_shift!=0)
 {
  lv_shift=0;
  lv_mode=3;
  RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
 }
}

void view_pg_up_ctrl()
{
 if (lv_pos==0)
  return;

 lv_pos=0;
 lv_mode=1;
 quick_view ();
 lv_mode=3;
 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
}

void view_pg_up()
{
 if (lv_pos==0)
  return;

 bool shift_pos=false;

 if (shift_key==true && shift_key2==false && shift_key3==true)
 {
  if (lv_pos<=lv_size/200)
  {
   lv_pos=0;
   lv_mode=1;
   quick_view ();
   lv_mode=3;

   RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
  }
  else
  {
   lv_pos=lv_pos30;

   lv_pos-=lv_size/200;

   view0=true;
   view_up ();
   view0=false;

   RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
  }
 }
 else if (lv_pos>0)
 {
  view0=true;
  int i=0;

  for (i=0; i<lv_lines; i++)
   view_up ();
 
  if (lv_mode==1)
   RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);

  view0=false;
 }
}

void view_pg_down_ctrl ()
{
 if (lv_pos30!=lv_size)
 {
  lv_pos=lv_size-1;
  shift_key2=true;

  view0=true;
  view_pg_up ();
  quick_view ();

  for (int i=0; i<lv_lines; i++)
  {
   if (lv_pos30>=lv_size)
    break;

   view_down ();
   quick_view ();
  }

  view0=false;
  RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);

  shift_key2=false;
 }
}

void view_pg_down()
{
 unsigned long pos=lv_pos;
 bool rw=true;

 if (shift_key==true && shift_key3==true)
 {
  if (lv_pos+lv_size/200>=lv_size)
  {
   view_pg_down_ctrl ();
   rw=false;
  }
  else
  {
   lv_pos+=lv_size/200;

   shift_key2=true;
   view_pg_up ();
   shift_key2=false;
   rw=false;
  }
 }
 else if (lv_pos30!=lv_size)
  lv_pos=lv_pos30;
 else
  return;

 if (rw==true)
 {
  lv_mode=1;
  quick_view ();
  
  if (lv_over==false)
  {
   lv_mode=3;
   RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
  }
  else
  {
   lv_mode=1;
   lv_pos=pos;
   quick_view ();

   view0=true;
   for (int i=0; i<lv_lines; i++)
   {
    if (lv_pos30>=lv_size)
     break;

    view_down ();
    quick_view ();
   }
   view0=false;
   RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);

   lv_over=false;
  }
 }
}

void view_max (int lpar)
{
 int i, t_hilight=lv_hilight, t_hilight2;

 lv_hilight=0;
 high_light ();

 lv_lines=int (HIWORD (lpar)/(lv_h0/32));
 if (lv_lines>lv_lines1)
  lv_lines=lv_lines1;

 lv_cols=int (LOWORD (lpar)*89/(lv_w0-6));
 if (lv_cols>lv_cols1)
  lv_cols=lv_cols1;

 t_hilight2=lv_hilight;
 lv_hilight=0;
 high_light ();

 view0=true;
 for (i=0; i<(lv_hilight-t_hilight2); i++)
  view_up ();
 view0=false;
 lv_hilight=t_hilight;

 lv_mode=1;

 if (lv_hilight!=0)
 {
  lv_hilight=0;
  high_light ();
 }

 for (i=0; i<lv_lines; i++)
  memset (lv_txt [i], 0, lv_range_mx);

 lv_cls=true;
 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);

 lv_max=1;
}

void view_min (int lpar)
{
 if (lv_init==true)
  return;

 int i, t_hilight=lv_hilight, t_hilight2;

 lv_lines=lv_lines0;
 lv_cols=lv_cols0;

 t_hilight2=lv_hilight;
 lv_hilight=0;
 high_light ();

 view0=true;
 for (i=0; i<(t_hilight2-lv_hilight); i++)
 {
  view_down ();
  quick_view ();
 }
 view0=false;
 lv_hilight=t_hilight;

 lv_mode=1;

 if (lv_hilight!=0)
 {
  lv_hilight=0;
  high_light ();
 }

 lv_cls=true;
 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);

 lv_max=0;
}

char keys [256] [2];

void load_keys ()
{
 int i, i2;
 for (i=0; i<256; i++)
  for (i2=0; i2<2; i2++)
   keys [i] [i2]='\0';

 keys [32] [0]=' ';

 keys [192] [0]='`'; keys [192] [1]='~';

 keys [48] [1]=')';
 keys [49] [1]='!';
 keys [50] [1]='@';
 keys [51] [1]='#';
 keys [52] [1]='$';
 keys [53] [1]='%';
 keys [54] [1]='^';
 keys [55] [1]='&';
 keys [56] [1]='*';
 keys [57] [1]='(';

 keys [189] [0]='-'; keys [189] [1]='_';
 keys [187] [0]='='; keys [187] [1]='+';
 keys [219] [0]='['; keys [219] [1]='{';
 keys [221] [0]=']'; keys [221] [1]='}';
 keys [220] [0]='\\'; keys [220] [1]='|';
 keys [186] [0]=';'; keys [186] [1]=':';
 keys [222] [0]='\''; keys [222] [1]='"';
 keys [188] [0]=','; keys [188] [1]='<';
 keys [190] [0]='.'; keys [190] [1]='>';
 keys [191] [0]='/'; keys [191] [1]='?';

 keys [111] [0]='/';
 keys [106] [0]='*';
 keys [109] [0]='-';
 keys [107] [0]='+';
}

void seek_add (int add)
{
 bool shift=false;
 char addc [2];

 if (GetKeyState (VK_CAPITAL))
 {
  if (!shift_key)
   shift=true;
 }
 else if (shift_key)
  shift=true;

 if (strlen (seek)<16)
 {
  if ((add>=65 && add<=90))
  {
   if (!shift)
    add+=32;

   sprintf (addc, "%c", add);
  }
  else
  {
   if (add>=48 && add<=57)
    sprintf (addc, "%c", add);

   if (!shift && keys [add] [0]!='\0')
    sprintf (addc, "%c", keys [add] [0]);
   else if (shift && keys [add] [1]!='\0')
    sprintf (addc, "%c", keys [add] [1]);
  }

  strcat (seek, addc);

  RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
 }
}

void bs ()
{
 if (strlen (seek)>0)
 {
  seek [strlen (seek)-1]='\0';
  RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
 }
}

// This function is called by the Windows function DispatchMessage ()
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 switch (message)// handle the messages
 {
  case WM_KEYDOWN:

   if (lv_capture)
   {
    KillTimer (hwnd, TIMER_CAPTURE);
    lv_capture=false;
    RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
   }

   if ((wParam>=65 && wParam<=90) || (wParam>=48 && wParam<=57) || strlen (keys [wParam]))
   {
    seek_add (wParam);
    break;
   }

   switch (wParam)
   {
    case VK_BACK:
     bs ();
     break;
    case VK_DOWN:
     view_down ();
     break;
    case VK_UP:
     view_up ();
     break;
    case VK_RIGHT:
     view_right ();
     break;
    case VK_LEFT:
     view_left ();
     break;
    case VK_END:
     view_end ();
     break;
    case VK_HOME:
     view_home ();
     break;
    case VK_RETURN:
     init_off=true;
     break;
    case VK_ESCAPE:
     save_conf ();
     PostQuitMessage (0);// send a WM_QUIT to the message queue
     break;

    case VK_NEXT:
     if (ctrl_key==true)
      view_pg_down_ctrl ();
     else
      view_pg_down ();
     break;
    case VK_PRIOR:
     if (ctrl_key==true)
      view_pg_up_ctrl ();
     else
      view_pg_up ();
     break;

    case VK_CONTROL:
     ctrl_key=true;
     break;
    case VK_SHIFT:
     shift_key=true;
     break;
   }
   break;

  case WM_KEYUP:

   switch (wParam)
   {
    case VK_CONTROL:
     ctrl_key=false;
     break;
    case VK_SHIFT:
     shift_key=false;
     break;
    case VK_RETURN:
     if (init_off)
     {
      lv_capture=true;
      capture ();
      SetTimer (hwnd, TIMER_CAPTURE, 500, NULL);
     }
     break;
    case VK_INSERT:
     hl_out ();
     break;
   }
   break;

  case WM_TIMER:
 
   switch (wParam)
   {
    case TIMER_CAPTURE:
     KillTimer (hwnd, TIMER_CAPTURE);
     lv_capture=false;
     RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE);
     break;
   }
   break;

  case WM_MOVE:

   GetWindowRect (hwnd, &Rect);
   if (Rect.left>0)
    min_r_left=Rect.left;
   if (Rect.top>0)
    min_r_top=Rect.top;
   break;

  case WM_SIZE:

   switch (wParam)
   {
    case SIZE_MAXIMIZED:
     view_max (lParam);
     break;
    case SIZE_RESTORED:
     if (lv_init || no_rest)
      break;

     // screen less than window - tweaks
     LONG a=GetWindowLongA (hWnd, GWL_STYLE);
     if (!(a & WS_MAXIMIZE))
     {
      GetClientRect (hwnd, &Rect);
      if (Rect.right!=lv_w0 || Rect.bottom!=lv_h0)
      {
       no_rest=true;
       SetWindowPos (hwnd, HWND_TOP, min_r_left, min_r_top, lv_w, lv_h, SWP_NOMOVE);
       no_rest=false;
      }

      view_min (lParam);
     }
     break;
   }
   break;

  case WM_KILLFOCUS:
   ctrl_key=false;
   shift_key=false;
   break;

  case WM_SETFOCUS:
   break;

  case WM_PAINT:
   if (lv_init==false)
    paint ();
   break;

  case WM_DESTROY:
   save_conf();
   PostQuitMessage (0);// send a WM_QUIT to the message queue
   break;
  default:// for messages that we don't deal with
   return DefWindowProc (hwnd, message, wParam, lParam);
 }

 return 0;
}

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
{
 lv_init=true;

 gThisInstance=hThisInstance;
 gFunsterStil=nFunsterStil;

 // The Window structure
 wincl.hInstance=hThisInstance;
 wincl.lpszClassName=szClassName;
 wincl.lpfnWndProc=WindowProcedure;// This function is called by windows
 wincl.style=CS_DBLCLKS;// Catch double-clicks
 wincl.cbSize=sizeof (WNDCLASSEX);

 wincl.hIcon=LoadIcon (hThisInstance, MAKEINTRESOURCE(ID_PIC));
 wincl.hIconSm=LoadIcon (hThisInstance, MAKEINTRESOURCE(ID_PIC));
 wincl.hCursor=LoadCursor (NULL, IDC_ARROW);

 wincl.lpszMenuName=NULL;// No menu
 wincl.cbClsExtra=0;// No extra bytes after the window class
 wincl.cbWndExtra=0;// structure or the window instance

 wincl.hbrBackground=(HBRUSH)CreateSolidBrush (RGB (0,0,0));

 // Register the window class, and if it fails quit the program 
 if (!RegisterClassEx (&wincl))
  return 0;

 int i, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0, i10=0, i11=0, s=0;
 
 char txt [_MAX_PATH];
 memset (txt, 0, _MAX_PATH);
 GetModuleFileName (NULL, txt, _MAX_PATH);
 for (i=_MAX_PATH-1; i>=0 && ap_l==0; i--)
 {
  if (txt [i]=='\\')
   ap_l=i+1;
 }

 for (i=0; i<ap_l; i++)
  AppPath [i]=txt [i];

 FILE *file;
 char conf [1024], conlv_wx [1024], conlv_wy [1024], conlv_range [1024], conlv_hilight [1024], conlv_max [1024],
 conlv_pos [1024], conlv_shift [1024], conlv_size [1024], conlv_path2 [1024], conlv_snap [1024], conlv_seek [1024];
 memset (conf, 0, 1024);
 memset (conlv_wx, 0, 1024);
 memset (conlv_wy, 0, 1024);
 memset (conlv_range, 0, 1024);
 memset (conlv_hilight, 0, 1024);
 memset (conlv_max, 0, 1024);
 memset (conlv_pos, 0, 1024);
 memset (conlv_shift, 0, 1024);
 memset (conlv_size, 0, 1024);
 memset (conlv_path2, 0, 1024);
 memset (conlv_snap, 0, 1024);
 memset (conlv_seek, 0, 1024);

 memset (path, 0, _MAX_PATH);
 memset (path2, 0, _MAX_PATH);
 memcpy (path, AppPath, ap_l);
 strcat (path, "data\\config.txt");

 int c=0;

 bool qt2=false;
 for (c=0; c<_MAX_PATH; c++)
 {
  if (lpszArgument [c]==34)
   qt2=true;
  else if (lpszArgument [c]==0)
   break;
 }

 if (c>2)
 {
  if (qt2==true)
  {
   for (i=0; i<c-2; i++)
    path2 [i]=lpszArgument [i+1];
   path2_l=c-2;
  }
  else
  {
   for (i=0; i<c; i++)
    path2 [i]=lpszArgument [i];
   path2_l=c;
  }
 }
 else
 {
  memcpy (path2, AppPath, ap_l);
  strcat (path2, "data\\readme.txt");
  path2_l=ap_l+15;
 }

 file=fopen (path, "r");
 if (file!=NULL)
 {
  fread (conf, 1, 1024, file);
  fclose (file);
     
  for (i=0; i<1024; i++)
  {
   if (conf [i])
   {
    if(s==0)
    {
     if (conf [i]=='\n')
      s=1;
     else
     {
      conlv_range [i1]=conf [i];
      i1++;
     }
    }
    else if(s==1)
    {
     if (conf [i]=='\n')
      s=2;
     else
     {
      conlv_wx [i2]=conf [i];
      i2++;
     }
    }
    else if(s==2)
    {
     if (conf [i]=='\n')
      s=3;
     else
     {
      conlv_wy [i3]=conf [i];
      i3++;
     }
    }
    else if(s==3)
    {
     if (conf [i]=='\n')
      s=4;
     else
     {
      conlv_hilight [i4]=conf [i];
      i4++;
     }
    }
    else if (s==4)
    {
     if (conf [i]=='\n')
      s=5;
     else
     {
      conlv_max [i5]=conf [i];
      i5++;
     }
    }
    else if (s==5)
    {
     if (conf [i]=='\n')
      s=6;
     else
     {
      conlv_pos [i6]=conf [i];
      i6++;
     }
    }
    else if (s==6)
    {
     if (conf [i]=='\n')
      s=7;
     else
     {
      conlv_shift [i7]=conf [i];
      i7++;
     }
    }
    else if (s==7)
    {
     if (conf [i]=='\n')
      s=8;
     else
     {
      conlv_size [i8]=conf [i];
      i8++;
     }
    }
    else if (s==8)
    {
     if (conf [i]=='\n')
      s=9;
     else
     {
      conlv_path2 [i9]=conf [i];
      i9++;
     }
    }
    else if (s==9)
    {
     if (conf [i]=='\n')
      s=10;
     else
     {
      conlv_snap [i10]=conf [i];
      i10++;
     }
    }
    else if (s==10)
    {
     if (conf [i]=='\n')
      s=11;
     else
     {
      conlv_seek [i11]=conf [i];
      i11++;
     }
    }
   }
  }

  memset (seek, 0, 16);
  memcpy (seek, conlv_seek, 12);

  if (i1!=0)
   lv_range=atoi (conlv_range);
  if (lv_range<lv_range0 || lv_range>lv_range1)
   lv_range=lv_range2;// default

  int twx=0, twy=0;
  if (i2!=0)
   twx=atoi (conlv_wx);
  if (i3!=0)
   twy=atoi (conlv_wy);
  if (twx>0 && twx<sx-50 && twy>0 && twy<sy-50)
  {
   wx=twx;
   wy=twy;
  }

  min_r_left=wx;
  min_r_top=wy;

  if (i4!=0)
   lv_hilight=atoi (conlv_hilight);
  if (lv_hilight!=0)
  {
   lv_hilight=0;
   high_light ();
  }

  if (i5!=0)
   lv_max=atoi (conlv_max);
  if (lv_max!=0)
   lv_max=1;
  else
   lv_max=0;
 }

 char title0 [11]={'L', 'o', 'g', 'V', 'i', 'e', 'w', 'e', 'r', ':', ' '};
 char title1 [lv_cols_mx];
 char title [100];
 memset (title, 0, 100);
 memset (title1, 0, lv_cols_mx);
 for (c=path2_l-1; c>=0; c--)
  if (path2 [c]=='\\')
   break;

 memset (path3, 0, _MAX_PATH);
 for (i=0; i<c+1; i++)
  path3 [i]=path2 [i];
 path3_l=c+1;

 for (i=c+1; i<path2_l; i++)
  title1 [i-c-1]=path2 [i];

 for (i=0; i<11; i++)
  title [i]=title0 [i];

 strcat (title, title1);
 strcat (g_title, title1);

 // The class is registered, let's create the program
 hwnd=CreateWindowEx (
  0,// Extended possibilites for variation
  szClassName,// Classname
  title,// Title Text
  WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
  wx,// The position
  wy,// where the window begins up on the screen
  250,// The programs width
  250,// and height in pixels
  HWND_DESKTOP,// The window is a child-window to desktop
  NULL,// No menu
  hThisInstance,// Program Instance handler
  NULL// No Window Creation data
 );

 // Make the window visible on the screen
 ShowWindow (hwnd, nFunsterStil);

 GetClientRect(hwnd, &Rect);
 int cap_add=225-Rect.bottom;
 lv_h=lv_h1+cap_add;
 yoff+=cap_add;

 SetWindowPos (hwnd, HWND_TOP, wx, wy, lv_w, lv_h, SWP_NOMOVE);
 hWnd=hwnd;

 if (lv_max==1)
  ShowWindow (hwnd, SW_MAXIMIZE);

 unsigned long t_fs;
 WIN32_FIND_DATA FindFileData;
 HANDLE t_h;
 t_h=FindFirstFile (path2, &FindFileData);
 if (t_h!=INVALID_HANDLE_VALUE)
 t_fs=(FindFileData.nFileSizeHigh*21474836470/10*2+FindFileData.nFileSizeLow)/1024;//...0/10?
 {
  if (t_fs>mx_len/1024)
  {
   lv_sp=(mx_len/1024)*100/t_fs;
   too_long=true;
  }
 }

 lv_file=fopen (path2, "rb");
 if (lv_file!=NULL)
 {
  fseek (lv_file, 0, SEEK_END);// seek to end of file
  if (!too_long)
  {
   lv_size=ftell (lv_file);// get current file pointer
   if (lv_size>mx_len)
   {
    lv_sp=mx_len/(lv_size/100);
    lv_size=mx_len;
    too_long=true;
   }
  }
  else
   lv_size=mx_len;
  if (lv_size/200<lv_range*lv_lines)
   shift_key3=false;

  if (i6!=0 && i8!=0 && i9!=0)
  {
   bool p_pos=true;
   for (i=0; i<path2_l; i++)
   {
    if (path2 [i]!=conlv_path2 [i])
     p_pos=false;
   }
   if (p_pos==false)
   {
    p_pos=true;

    for (i=0; i<path2_l; i++)
    {
     if (path2 [i]=='/' || path2 [i]=='\\')
      break;
     if (path2 [path2_l-i]!=conlv_path2 [i9-i])
      p_pos=false;
    }
    if (lv_size!=atoi (conlv_size))
     p_pos=false;
   }

   if (p_pos==true)
   {
    if (atoi (conlv_size)>lv_size)
     p_pos=false;
   }

   if (p_pos==true)
   {
    unsigned long t_i0=atoi (conlv_pos)-2, t_i1=atoi (conlv_pos)+2;
    int t_int [10], t_int2, t_pos=0, t_i=0, t_c, t_c2=0, t_c3=0;
    char t_char [3];

    for (i=0; i<i10; i++)
    {
     if (conlv_snap [i]==' ')
     {
      memset (t_char, 0, 3);
      t_c=0;
      for (t_i=t_pos; t_i<i && t_c<3; t_i++)
      {
       t_char [t_c]=conlv_snap [t_i];
       t_c++;
      }
      t_pos=i+1;

      t_int [t_c2]=atoi (t_char);
      t_c2++;
     }
    }

    if ((int)t_i0<0)
     t_i0=0;

    if (t_i1>atoi (conlv_size))
     t_i1=atoi (conlv_size);

    while (t_c3<5)
    {
     fseek (lv_file, t_i0, SEEK_SET);
     t_int2=fgetc (lv_file);
     if (t_int2!=t_int [t_c3])
      p_pos=false;
     if (t_i0<t_i1)
      t_i0++;
     t_c3++;
    }

    while (t_c3<10)
    {
     t_i0=atoi (conlv_pos)/20*t_c3+10;
     if ((int)t_i0<0)
      t_i0=0;
     if (t_i0>atoi (conlv_size))
      t_i0=atoi (conlv_size);
     fseek (lv_file, t_i0, SEEK_SET);
     t_int2=fgetc (lv_file);
     if (t_int2!=t_int [t_c3])
      p_pos=false;
     t_c3++;
    }
   }
   else
   {
    fseek (lv_file, 0, SEEK_SET);
    fgetc (lv_file);
   }

   if (p_pos==true)
   {
    lv_pos=atoi (conlv_pos);
    lv_shift=atoi (conlv_shift);
   }
  }
 }

 hf=CreateFont (18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Courier");

 load_keys ();

 lv_init=false;

 // Run the message loop. It will run until GetMessage () returns 0
 while (GetMessage (&messages, NULL, 0, 0))
 {
  // Translate virtual-key messages into character messages
  TranslateMessage (&messages);
  // Send message to WindowProcedure
  DispatchMessage (&messages);
 }

 // The program return-value is 0 - The value that PostQuitMessage () gave
 return messages.wParam;
}