// WinGUI.cpp : Defines the entry point for the application.
// Author : Murat Guler

#include "stdafx.h"
#include "resource.h"
#include <commctrl.h>
#include "gui.h"
#include "Parse.h"

/* Global Tables */
// Message Dispatch Table

const struct decodeUINT MainMessages[] = {
 WM_CREATE, DoCreateMain,
 WM_DESTROY, DoDestroyMain,
 WM_SIZE, DoSizeMain,
 WM_COMMAND, DoCommandMain,
};

const struct decodeCMD MainCommandItems[] = {
 ID_FILE_EXIT, DoMainCommandExit,
 ID_FILE_OPEN, DoMainCommandOpen,
};

const struct decodeUINT ClientMessages[] = {
    WM_CREATE, DoCreateClient,
    WM_PAINT, DoPaintClient,
 WM_VSCROLL, DoVScrollClient,
};

// Message dispatch table for EditWndWindowProc
/*const struct decodeUINT EditWndMessages[] = {
    WM_CREATE, DoCreateEditWnd,
    WM_COMMAND, DoCommandEditWnd,
};*/

/* Global Variables */
HINSTANCE hInst;
//TCHAR *stText = TEXT("This is a test of the GUI for the Windows CE Application Project.  This test will enable us to see whether the text written here will fit into the application window properly. \n authors:  Murat Guler, Jian Liu, Yannick Fortin.\n\0");
TCHAR szClassName[ ] = TEXT("WinCE Browser");
LPCTSTR lpstGlobalFileName = TEXT("output.txt");
INT sVPos = 0;
INT sVMax = 0;
BOOL fFirst = TRUE;
BOOL fReallyFirst = TRUE;
LPCTSTR lpstErrorFile = TEXT("\\Windows\\error.txt");
//LPTSTR lpstURL = TEXT("/489X/4894O.html");
LPTSTR lpstURL;
 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
    //HWND hwnd;               /* This is the handle for our window */
    MSG msg;                   /* Here messages to the application is saved */
    int rc;                    /* Return Code */
    //WNDCLASS wincl;        /* Datastructure for the windowclass */

    // Initializing Application
    rc = InitApp (hInstance);
    if (rc) return rc;

    // Initializing Instance
    rc = InitInstance (hInstance, lpCmdLine, nCmdShow);
    if (rc) return rc;

    /* Run the nessageloop. It will run until GetMessage( ) returns 0 */
    while(GetMessage(&msg, NULL, 0, 0))
    {
           TranslateMessage(&msg);
           DispatchMessage(&msg);
    }

    /* The program returvalue is 0 - The value that PostQuitMessage( ) gave */
    return TermInstance (hInstance, msg.wParam);
}

int InitApp (HINSTANCE hInstance)
{
    WNDCLASS wc;

    wc.hInstance = hInstance;
    wc.lpszClassName = szClassName;
    wc.lpfnWndProc = MainWndProc;    /* This function is called by windows */
    wc.style = 0;        /* Ctach double-clicks */

    /* Use default icon and mousepointer */
    wc.hIcon = NULL;
    wc.hCursor = NULL;
    wc.lpszMenuName = NULL;     /* No menu */
    wc.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wc.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use lightgray as the background of the window */
    wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);

    /* Register the window class, if fail quit the program */
    if (RegisterClass(&wc) == 0) return 1;

 // Initializing the child window
 if (InitClient(hInstance) != 0) return 2;

 // Initializing the edit window
 /*if (InitEditWnd(hInstance) != 0) return 2;*/
    return 0;
}

int InitInstance (HINSTANCE hInstance, LPWSTR lpCmdLine, int nCmdShow)
{
    HWND hwnd;

 //Save program instance in global variable
 hInst = hInstance;

 lpstURL = (LPTSTR) malloc(128*sizeof(TCHAR));

 //Create main window
    hwnd = CreateWindow(
           szClassName,         /* Classname */
           TEXT("WinCE Browser"),   /* Title Text */
           WS_VISIBLE,   /* defaultwindow */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window end up on the screen */
           CW_USEDEFAULT,       /* The programs width */
           CW_USEDEFAULT,       /* and height in pixels */
           NULL,        /* The window is a childwindow to desktop */
           NULL,                /* No menu */
           hInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );
    // Return error code if window is not created.
    if (!IsWindow (hwnd)) return 0x10;

    /* Make the window visible on the screen */
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow (hwnd);
    return 0;
}

int TermInstance (HINSTANCE hInstance, int nDefRC) {
 return nDefRC;
}

/* This function is called by the Windowsfunction DispatchMessage( ) */
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 int i;

 for (i=0; i<dim(MainMessages); i++) {
  if (msg == MainMessages[i].Code) {
   return (*MainMessages[i].Fxn)(hwnd, msg, wParam, lParam);
  }
 }
 return DefWindowProc (hwnd, msg, wParam, lParam);
}

LRESULT DoCreateMain (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  HWND hwndCB, hwndClient;
  //HWND hwndEdit;
  int sHeight;
  LPCREATESTRUCT lpcs;

  // Convert lParam into pointer to create structure.
  lpcs = (LPCREATESTRUCT) lParam;

        // Creating command bar
        hwndCB = CommandBar_Create (hInst, hwnd, IDC_CMDBAR);
  // Add the menu
  CommandBar_InsertMenubar (hwndCB, hInst, IDR_GUIMENU, 0);
        // Adding exit button
        CommandBar_AddAdornments (hwndCB, 0, 0);
  sHeight = CommandBar_Height (GetDlgItem (hwnd, IDC_CMDBAR));
  /*hwndEdit = CreateWindow (EDITWINDOW, TEXT ("Open URL"),
        WS_VISIBLE | WS_CHILD | WS_BORDER,
        lpcs->x, lpcs->y + sHeight,
        lpcs->cx, BOX_HEIGHT,
        hwnd, (HMENU) IDC_EDITBOX,
        lpcs->hInstance, NULL);*/
  hwndClient = CreateWindow (CLIENTWINDOW, TEXT (""),
        WS_VISIBLE | WS_CHILD | WS_VSCROLL,
        lpcs->x, lpcs->y + sHeight,
        lpcs->cx, lpcs->cy - sHeight,
        hwnd, (HMENU)IDC_CLIENT,
        lpcs->hInstance, NULL);
  // Destroy frame if client window not created.
  if (!IsWindow (hwndClient))
   DestroyWindow (hwnd);
  return 0;
}

LRESULT DoSizeMain (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  RECT rect;
  INT i;

     GetClientRect (hwnd, &rect);
  i = CommandBar_Height (GetDlgItem (hwnd, IDC_CMDBAR));
  rect.top += i;
  //rect.top += BOX_HEIGHT;

     SetWindowPos (GetDlgItem (hwnd, IDC_CLIENT), NULL, rect.left, rect.top,
                rect.right - rect.left, rect.bottom - rect.top,
             SWP_NOZORDER);
  return 0;
}

LRESULT DoDestroyMain (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
        PostQuitMessage (0);
        return 0;
}

int InitClient (HINSTANCE hInstance)
{
    WNDCLASS wc;

    // Register application client window class.
    wc.style = 0;                             // Window style
    wc.lpfnWndProc = ClientWndProc;           // Callback function
    wc.cbClsExtra = 0;                        // Extra class data
    wc.cbWndExtra = 0;                        // Extra window data
    wc.hInstance = hInstance;                 // Owner handle
    wc.hIcon = NULL,                          // Application icon
    wc.hCursor = NULL;                        // Default cursor
    wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wc.lpszMenuName =  NULL;                  // Menu name
    wc.lpszClassName = CLIENTWINDOW;          // Window class name

    if (RegisterClass (&wc) == 0) return 1;

    return 0;
}

int TermClient (HINSTANCE hInstance, int nDefRC)
{

    return nDefRC;
}

LRESULT CALLBACK ClientWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,
                                LPARAM lParam) {
    INT i;
    //
    // Search message list to see if we need to handle this
    // message.  If in list, call procedure.
    //
    for (i = 0; i < dim(ClientMessages); i++) {
        if (wMsg == ClientMessages[i].Code)
            return (*ClientMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
    }
    return DefWindowProc (hWnd, wMsg, wParam, lParam);
}

LRESULT DoCreateClient (HWND hwnd, UINT wMsg, WPARAM wParam,
                        LPARAM lParam) {
    //HDC hdc;
    //INT i, rc;

    //Enumerate the available fonts... For a future version maybe...
    /*hdc = GetDC (hwnd);
    rc = EnumFontFamilies ((HDC)hdc, (LPTSTR)NULL, FontFamilyCallback, 0);

    for (i = 0; i < sFamilyCnt; i++) {
        ffs[i].nNumFonts = 0;
        rc = EnumFontFamilies ((HDC)hdc, ffs[i].szFontFamily,
                               EnumSingleFontFamily,
                               (LPARAM)(PFONTFAMSTRUCT)&ffs[i]);
    }
    ReleaseDC (hWnd, hdc);*/
    return 0;
}

LRESULT DoPaintClient (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
        PAINTSTRUCT ps;
  INT iOldtop;
        RECT rect;
        HDC hdc;
  TCHAR *stWebText;
  DWORD dwCharsRead = 0;
  DWORD dwTextLength = 0;
  SCROLLINFO si;

        // Getting the web text file.
  stWebText = (TCHAR *) malloc(128000*sizeof(TCHAR));
  if (ReadWebPage(stWebText, &dwCharsRead))
   return 1;
  FindTextLength (stWebText, dwCharsRead, &dwTextLength);

  // Adjusting size of rectangle by deducing the position of scroll bar
  // This is a devious plan to shift the text up and down. - M.G.
        GetClientRect (hwnd, &rect);
  //rect.top += BOX_HEIGHT;
  rect.top -= sVPos;

        hdc = BeginPaint (hwnd, &ps);
        SetBkMode (hdc, TRANSPARENT);
        //SetBkColor (hdc, COLOR_WHITE);
        SetTextColor (hdc, COLOR_BLACK);
        DrawText (hdc, stWebText, dwCharsRead, &rect, DT_LEFT | DT_WORDBREAK);
  if (fReallyFirst)
  {
   iOldtop = rect.top;
   fReallyFirst = FALSE;
  }

     if (fFirst)
  {
      sVPos = 0;
   sVMax = (dwTextLength - iOldtop) - (rect.bottom - iOldtop);

   si.cbSize = sizeof (si);
         si.nMin = 0;
      si.nMax = dwTextLength;
   si.nPage = rect.bottom - iOldtop;
         si.nPos = sVPos;
      si.fMask = SIF_ALL;

   SetScrollInfo (hwnd, SB_VERT, &si, TRUE);

   fFirst = FALSE;
  }
 
 
 

        EndPaint (hwnd, &ps);

  free (stWebText);
        return 0;
}

LRESULT DoVScrollClient (HWND hWnd, UINT wMsg, WPARAM wParam,
                         LPARAM lParam) {
    RECT rect;
    SCROLLINFO si;
    INT sOldPos = sVPos;

    GetClientRect (hWnd, &rect);
 //rect.top += BOX_HEIGHT;

    switch (LOWORD (wParam)) {
    case SB_LINEUP:
        sVPos -= 10;
        break;

    case SB_LINEDOWN:
        sVPos += 10;
        break;

    case SB_PAGEUP:
        sVPos -= rect.bottom - rect.top;
        break;

    case SB_PAGEDOWN:
        sVPos += rect.bottom - rect.top;
        break;

    case SB_THUMBPOSITION:
        sVPos = HIWORD (wParam);
        break;
    }
    // Check range.
    if (sVPos < 0)
        sVPos = 0;
    if (sVPos > sVMax)
        sVPos = sVMax;

    // If scroll position changed, update scrollbar and
    // force redraw of window.
    if (sVPos != sOldPos) {
        si.cbSize = sizeof (si);
        si.nPos = sVPos;
        si.fMask = SIF_POS;
        SetScrollInfo (hWnd, SB_VERT, &si, TRUE);

        InvalidateRect (hWnd, NULL, TRUE);
    }
    return 0;
}
 

/*int InitEditWnd (HINSTANCE hInstance)
{
 WNDCLASS wc;

    // Register application EditWnd window class.
    wc.style = 0;                             // Window style
    wc.lpfnWndProc = EditWndProc;             // Callback function
    wc.cbClsExtra = 0;                        // Extra class data
    wc.cbWndExtra = 0;                        // Extra window data
    wc.hInstance = hInstance;                 // Owner handle
    wc.hIcon = NULL,                          // Application icon
    wc.hCursor = NULL;                        // Default cursor
    wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wc.lpszMenuName =  NULL;                  // Menu name
    wc.lpszClassName = EDITWINDOW;               // Window class name

    if (RegisterClass (&wc) == 0) return 1;

    return 0;
}*/

/*LRESULT CALLBACK EditWndProc (HWND hwnd, UINT wMsg, WPARAM wParam,
         LPARAM lParam)
{
    INT i;
    //
    // Search message list to see if we need to handle this
    // message.  If in list, call procedure.
    //
    for (i = 0; i < dim(EditWndMessages); i++) {
        if (wMsg == EditWndMessages[i].Code)
            return (*EditWndMessages[i].Fxn)(hwnd, wMsg, wParam, lParam);
    }
    return DefWindowProc (hwnd, wMsg, wParam, lParam);
}*/

/*LRESULT DoCreateEditWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
                         LPARAM lParam)
{
 return 0;
}*/

/*LRESULT DoCommandEditWnd (HWND hWnd, UINT wMsg, WPARAM wParam,
                          LPARAM lParam)
{
 return 0;
}*/

LRESULT DoCommandMain (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  WORD idItem;
  HWND hwndCtl;
  WORD wNotifyCode;
  int i;

  idItem = (WORD) LOWORD (wParam);
  wNotifyCode = (WORD) HIWORD (wParam);
  hwndCtl = (HWND) lParam;
  for (i=0; i<dim(MainCommandItems); i++) {
   if (idItem == MainCommandItems[i].Code) {
    return (*MainCommandItems[i].Fxn)(hwnd, idItem, hwndCtl, wNotifyCode);
   }
  }
  return 0;
}

LPARAM DoMainCommandExit (HWND hwnd, WORD idItem, HWND hwndCtl, WORD wNotifyCode)
{
 SendMessage (hwnd, WM_CLOSE, 0, 0);
 return 0;
}

LPARAM DoMainCommandOpen (HWND hwnd, WORD idItem, HWND hwndCtl, WORD wNotifyCode)
{
 HANDLE hFile;

 DialogBox(hInst, MAKEINTRESOURCE(IDD_OPENDIALOG), hwnd, OpenDlgProc);
 //MessageBox (hwnd, lpstURL, NULL, MB_OK);
 DoInet (lpstURL, hwnd);

 if (!parse (TEXT("index.html")))
 {
  hFile = CreateFile (lpstErrorFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  CloseHandle (hFile);
  return 1;
 }
 fFirst = TRUE;
 InvalidateRect (hwnd, NULL, TRUE);
 return 0;
}

/* Reading the web page text file from Windows directory */
int ReadWebPage (TCHAR *stWebText, LPDWORD lpCharsRead)
{
 HANDLE hFile;
 BOOL Result;
 LPVOID lpFileBuffer;
 TCHAR *stScanner;
 DWORD i;

 hFile = CreateFile (lpstGlobalFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
 if (hFile == INVALID_HANDLE_VALUE)
  return 1;

 lpFileBuffer = stWebText;
 Result = ReadFile (hFile, lpFileBuffer, 128000, lpCharsRead, NULL);
 if (!(Result))
  return 1;

 *lpCharsRead /= 2;  // Converting number of bytes to number of unicode chars.

 // Deleting the first character in the file, since it causes problems...
 if (*lpCharsRead > 0)
 {
  stScanner = stWebText;
  stScanner++;
  for (i=1;i<(*lpCharsRead);i++)
  {
   *stWebText = *stScanner;
   stScanner++;
   stWebText++;
  }
  (*lpCharsRead)--;
 }

 Result = CloseHandle (hFile);
 if (!(Result))
  return 1;
 return 0;
}

/* Finds the length of the Text web page in terms of pixels */
int FindTextLength (TCHAR *stWebText, DWORD dwCharsRead, LPDWORD lpTextLength)
{
 DWORD iNumLines = 0;
 DWORD iColumn = 0;
 DWORD i;

 *lpTextLength = 0;
 if ((dwCharsRead == 0 ) || (stWebText == NULL))
  return 0;

 for (i=0; i<dwCharsRead; i++)
 {
  if (*stWebText == '\n')
  {
   iNumLines++;
   iColumn = 0;
  }
  else
  {
   iColumn++;
   if (iColumn > 46)
   {
    iNumLines++;
    iColumn = 0;
   }
  }
  stWebText++;
 }

 iNumLines++;
 *lpTextLength = iNumLines * FONTHEIGHT;
 return 0;
}

BOOL CALLBACK OpenDlgProc (HWND hwnd, UINT wMsg, WPARAM wParam,
                          LPARAM lParam)
{
 //TCHAR szURL[128];

 switch (wMsg)
 {
 case WM_INITDIALOG:
  SetDlgItemText (hwnd, IDC_URLEDIT, TEXT(""));
  /*SendDlgItemMessage (hwnd, IDC_URLEDIT, EM_LIMITTEXT,
   sizeof(lpstURL) - 1, 0);*/
  return TRUE;

 case WM_COMMAND:
  switch (LOWORD (wParam))
  {
  case IDOK:
   GetDlgItemText (hwnd, IDC_URLEDIT, lpstURL, 128);
   //MultiByteToWideChar(CP_ACP, 0, szURL, 128, lpstURL, 128);
   EndDialog (hwnd, 0);
   return TRUE;

  case IDCANCEL:
   EndDialog (hwnd, 0);
   return TRUE;
  }
  return FALSE;
 }

 return FALSE;
}