
/*
 * main window & setup dialog specific code
 */

// setup dialog callback function 

#include "dialog.h"

#define MESS(id,m,w,l) SendDlgItemMessage(h,id,m,(WPARAM)w,(LPARAM)l)
#define ER(m,w,l) MESS(ID_RESOLUTION,m,w,l)
#define EB(m,w,l) MESS(ID_BPP,m,w,l)

BOOL CALLBACK dialogproc(HWND h,UINT m,WPARAM w,LPARAM l)
{
        switch (m) {

                case WM_COMMAND:
                        switch (LOWORD(w)) {
                                case IDCANCEL:
                                case ID_STOP:
                                        EndDialog(h,0);
                                        return 1;
                                case ID_GO:
                                        EndDialog(h,1);
                                        return 1;
                                case ID_FULLSCREEN:
                                        fullscreen=SendDlgItemMessage(h,ID_FULLSCREEN,BM_GETCHECK,0,0);
                                        return 1;
                                case ID_VOODOO:
                                        Texture3DS::voodoo=SendDlgItemMessage(h,ID_VOODOO,BM_GETCHECK,0,0);
                                        return 1;
                                case ID_LOWTEXTURES:
                                        Texture3DS::lowtextures=SendDlgItemMessage(h,ID_LOWTEXTURES,BM_GETCHECK,0,0);
                                        return 1;
                                case ID_NOFOG:
                                        usefog=!SendDlgItemMessage(h,ID_NOFOG,BM_GETCHECK,0,0);
                                        return 1;
                                case ID_RESOLUTION:
                                        if (HIWORD(w)==CBN_SELCHANGE) {
                                        int s=ER(CB_GETCURSEL,0,0);
                                        switch (s) {
                                                case 0:
                                                        resx=320; resy=200;
                                                        break;
                                                case 1:
                                                        resx=320; resy=240;
                                                        break;
                                                case 2:
                                                        resx=400; resy=300;
                                                        break;
                                                case 3:
                                                        resx=512; resy=384;
                                                        break;
                                                case 4:
                                                        resx=640; resy=400;
                                                        break;
                                                case 5:
                                                        resx=640; resy=480;
                                                        break;
                                                case 6:
                                                        resx=720; resy=480;
                                                        break;
                                                case 7:
                                                        resx=800; resy=600;
                                                        break;
                                                case 8:
                                                        resx=848; resy=480;
                                                        break;
                                                case 9:
                                                        resx=1024; resy=768;
                                                        break;
                                                case 10:
                                                        resx=1280; resy=1024;
                                                        break;
                                                case 11:
                                                        resx=1600; resy=1200;
                                                        break;
                                                }
                                        }
                                        return 1;
                                case ID_BPP:
                                        if (HIWORD(w)==CBN_SELCHANGE) {
                                        int s=EB(CB_GETCURSEL,0,0);
                                        switch (s) {
                                                case 0:
                                                        bpp=16;
                                                        break;
                                                case 1:
                                                        bpp=24;
                                                        break;
                                                case 2:
                                                        bpp=32;
                                                        break;
                                                }
                                        }
                                        return 1;
                                }
                        break;

                case WM_INITDIALOG:

                        resx=640;resy=480;bpp=32;
                        fullscreen=TRUE;
                        Texture3DS::voodoo=FALSE;
                        Texture3DS::lowtextures=FALSE;
                        usefog=TRUE;

                        MESS(ID_FULLSCREEN,BM_SETCHECK,1,0);

                        ER(CB_ADDSTRING,0,"320 x 200");
                        ER(CB_ADDSTRING,0,"320 x 240");
                        ER(CB_ADDSTRING,0,"400 x 300");
                        ER(CB_ADDSTRING,0,"512 x 384");
                        ER(CB_ADDSTRING,0,"640 x 400");
                        ER(CB_ADDSTRING,0,"640 x 480");
                        ER(CB_ADDSTRING,0,"720 x 480");
                        ER(CB_ADDSTRING,0,"800 x 600");
                        ER(CB_ADDSTRING,0,"848 x 480");
                        ER(CB_ADDSTRING,0,"1024 x 768");
                        ER(CB_ADDSTRING,0,"1280 x 1024");
                        ER(CB_ADDSTRING,0,"1600 x 1200");
                        ER(CB_SETCURSEL,5,0);

                        EB(CB_ADDSTRING,0,"16");
                        EB(CB_ADDSTRING,0,"24");
                        EB(CB_ADDSTRING,0,"32");
                        EB(CB_SETCURSEL,2,0);

                        return 1;

        }
        return 0;
}


/*okno initialization*/

#ifndef CDS_FULLSCREEN
#define CDS_FULLSCREEN 4
#endif

bool      active=TRUE;


#define   VK_MOUSEL 256
#define   VK_MOUSER 257
#define   VK_PLUS VK_ADD
#define   VK_MINUS VK_SUBTRACT
#define   VK_A 65
#define   VK_Z 90
#define   VK_X 88
#define   VK_S 83
#define   VK_D 68
#define   VK_Q 81
#define   VK_E 69
bool      key[258];
int       mouse_x=320,mouse_y=240;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
        if (height==0)
        {
                height=1;
        }
        glViewport(0,0,width,height);
}

GLvoid KillGLWindow(GLvoid)                                                   
{
        if (fullscreen)                                                       
        {
                ChangeDisplaySettings(NULL,0);                                
                ShowCursor(TRUE);                                             
        }

        if (hRC)                                                                
        {
                if (!wglMakeCurrent(NULL,NULL))                                 
                {
                        MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
                }

                if (!wglDeleteContext(hRC))                                             
                {
                        MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
                }
                hRC=NULL;                                                                               
        }

        if (hDC && !ReleaseDC(hWnd,hDC))                                        
        {
                MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
                hDC=NULL;                                                                             
        }

        if (hWnd && !DestroyWindow(hWnd))                               
        {
                MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
                hWnd=NULL;                                              
        }

        if (!UnregisterClass("OpenGL",hInstance))                       
        {
                MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
                hInstance=NULL;                                                                
        }
}

void* memset (void* p, int a, size_t size)
{
  char b = a;
  char* ptr = (char*)p;
  for(int i=size; i; i--) {
    *ptr = b;
    ptr++;
  }
}

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
        GLuint          PixelFormat;        
        WNDCLASS        wc;                 
        DWORD           dwExStyle;          
        DWORD           dwStyle;            
        RECT            WindowRect;         
        WindowRect.left=(long)0;            
        WindowRect.right=(long)width;       
        WindowRect.top=(long)0;             
        WindowRect.bottom=(long)height;     

        fullscreen=fullscreenflag;          

        hInstance                       = GetModuleHandle(NULL);              
        wc.style                        = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
        wc.lpfnWndProc          = (WNDPROC) WndProc;                          
        wc.cbClsExtra           = 0;                                          
        wc.cbWndExtra           = 0;                                          
        wc.hInstance            = hInstance;                                  
        wc.hIcon                = LoadIcon(hInstance, MAKEINTRESOURCE(ID_ICON));
//        wc.hIcon                        = LoadIcon(NULL, IDI_WINLOGO);        
        wc.hCursor                      = LoadCursor(NULL, IDC_ARROW);        
        wc.hbrBackground        = NULL;                                       
        wc.lpszMenuName         = NULL;                                       
        wc.lpszClassName        = "OpenGL";                                   

        if (!RegisterClass(&wc))                                                                      
        {
                MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
                return FALSE;                                                                           
        }

        if (fullscreen)                                                                                 
        {
                DEVMODE dmScreenSettings;                                                               
                memset(&dmScreenSettings,0,sizeof(dmScreenSettings));   
                dmScreenSettings.dmSize=sizeof(dmScreenSettings);       
                dmScreenSettings.dmPelsWidth    = width;                
                dmScreenSettings.dmPelsHeight   = height;               
                dmScreenSettings.dmBitsPerPel   = bits;                 
                dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

                  if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
                {
                        if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
                        {
                                fullscreen=FALSE;               
                        }
                        else
                        {
                                MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
                                return FALSE;                                                                   // Return FALSE
                        }
                }
        }

        if (fullscreen)                                        
        {
                dwExStyle=WS_EX_APPWINDOW;                     
                dwStyle=WS_POPUP;                              
                ShowCursor(FALSE);                             
        }
        else
        {
                dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;  
                dwStyle=WS_OVERLAPPEDWINDOW;                   
        }

        AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);             

        // Create The Window
        if (!(hWnd=CreateWindowEx(      dwExStyle,                                                      
                                                                "OpenGL",                               
                                                                title,                                  
                                                                dwStyle |                               
                                                                WS_CLIPSIBLINGS |                       
                                                                WS_CLIPCHILDREN,                        

                                                                CW_USEDEFAULT, CW_USEDEFAULT,
//                                                                0, 0,                                   
                                                                WindowRect.right-WindowRect.left,       
                                                                WindowRect.bottom-WindowRect.top,       
                                                                NULL,                                   
                                                                NULL,                                   
                                                                hInstance,                              
                                                                NULL)))                                 
        {
                KillGLWindow();          
                MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
                return FALSE;            
        }

        static  PIXELFORMATDESCRIPTOR pfd=                              // pfd Tells Windows How We Want Things To Be
        {
                sizeof(PIXELFORMATDESCRIPTOR),                          // Size Of This Pixel Format Descriptor
                1,                                                                                      // Version Number
                PFD_DRAW_TO_WINDOW |                                            // Format Must Support Window
                PFD_SUPPORT_OPENGL |                                            // Format Must Support OpenGL
                PFD_DOUBLEBUFFER,                                                       // Must Support Double Buffering
                PFD_TYPE_RGBA,                                                          // Request An RGBA Format
                bits,                                                                           // Select Our Color Depth
                0, 0, 0, 0, 0, 0,                                                       // Color Bits Ignored
                0,                                                                                      // No Alpha Buffer
                0,                                                                                      // Shift Bit Ignored
                0,                                                                                      // No Accumulation Buffer
                0, 0, 0, 0,                                                                     // Accumulation Bits Ignored
                16,                                                                                     // 16Bit Z-Buffer (Depth Buffer)
                0,                                                                                      // No Stencil Buffer
                0,                                                                                      // No Auxiliary Buffer
                PFD_MAIN_PLANE,                                                         // Main Drawing Layer
                0,                                                                                      // Reserved
                0, 0, 0                                                                         // Layer Masks Ignored
        };

        if (!(hDC=GetDC(hWnd)))                         
        {
                KillGLWindow();                                                        
                MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
                return FALSE;                                                          
        }

        if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) 
        {
                KillGLWindow();                                                        
                MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
                return FALSE;                                                          
        }

        if(!SetPixelFormat(hDC,PixelFormat,&pfd))       
        {
                KillGLWindow();                                                        
                MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
                return FALSE;                                                          
        }

        if (!(hRC=wglCreateContext(hDC)))               
        {
                KillGLWindow();                                                        
                MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
                return FALSE;                                                           
        }

        if(!wglMakeCurrent(hDC,hRC))                    
        {
                KillGLWindow();                                                        
                MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
                return FALSE;                                                           
        }

        ShowWindow(hWnd,SW_SHOW);                                   
        SetForegroundWindow(hWnd);                                  
        SetFocus(hWnd);                                             
        ReSizeGLScene(width, height);                               

        if (!InitGL())                                              
        {
                KillGLWindow();                                                        
                MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
                return FALSE;                                                        
        }

        return TRUE;                                                                 
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM  wParam, LPARAM lParam)
{
        switch (uMsg)                                                          
        {
                case WM_ACTIVATE:                                              
                {
                        if (!HIWORD(wParam))                                   
                        {
                                active=TRUE;                                   
                        }
                        else
                        {
                                active=FALSE;                                  
                        }

                        return 0;                                              
                }

                case WM_SYSCOMMAND:                                            
                {
                        switch (wParam)                                        
                        {
                                case SC_SCREENSAVE:                            
                                case SC_MONITORPOWER:                          
                                return 0;                                      
                        }
                        break;                                                 
                }

                case WM_CLOSE:                                                 
                {
                        PostQuitMessage(0);                                    
                        return 0;                                              
                }

                case WM_KEYDOWN:                                               
                {
                        key[wParam] = TRUE;                                    
                        return 0;                                              
                }

                case WM_KEYUP:                                                 
                {
                        key[wParam] = FALSE;                                   
                        return 0;                                              
                }
                case WM_MOUSEMOVE:
                  {
                  mouse_x = ((int) LOWORD(lParam) << 16) >> 16;
                  mouse_y = ((int) HIWORD(lParam) << 16) >> 16;
                  break;
                  }
                case WM_LBUTTONDOWN:
                  {
                  key[VK_MOUSEL]=1;
                  break;
                  }
                case WM_LBUTTONUP:
                  {
                  key[VK_MOUSEL]=0;
                  break;
                  }
                case WM_RBUTTONDOWN:
                  {
                  key[VK_MOUSER]=1;
                  break;
                  }
                case WM_RBUTTONUP:
                  {
                  key[VK_MOUSER]=0;
                  break;
                  }
                case WM_SIZE:                                          
                {
                        ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));  
                        return 0;                                      
                }
        }

        // Pass All Unhandled Messages To DefWindowProc
        return DefWindowProc(hWnd,uMsg,wParam,lParam);
}