/********************************************************************

               Windows interface for final project

                   (C)Adam Hatherly 2000

*********************************************************************/

#include <string.h>

#include <math.h>


#ifndef GLOBAL_DECL

#include "global.h"     // Global data types and variables

#endif


// Global Variables

LRESULT CALLBACK WndProc        (HWND, UINT, WPARAM, LPARAM);
BOOL    CALLBACK OptionsDlgProc (HWND, UINT, WPARAM, LPARAM);
FARPROC lpfnOptionsDlgProc;
BOOL    CALLBACK AboutDlgProc   (HWND, UINT, WPARAM, LPARAM);
FARPROC lpfnAboutDlgProc;

char      szAppName[] = "WebNewsSpeak";     // Window Name

char      szCaption[] = "Web News Speak";   // Window Caption

HWND      hButtons[10];                     // Button handles

HWND      hChecks[10];                      // Check box handles

int       ButtonFocus;                      // Index of the button with focus

buttons   mbuttons;                         // Object maintaining button values

int       WinMaWid;                         // Width of main window

int       WinMaHei;                         // Height of main window

bool      Timer_Set = false;                // The timer for downloading is not set

                                            
pglist      *pagelist;                      // Ptr to linked list of pages

config      *settings;                      // Object to maintain user settings

statuswnd   *status;                        // Pointer to status window object


// Subclassed window procedures - different types on different version of the compiler - why?

#if COMPILER_V6

WNDPROC OldButProc;
WNDPROC OldCheckProc;
#else

FARPROC OldButProc;
FARPROC OldCheckProc;
#endif


// Implementation

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
    MSG         msg;
    WNDCLASSEX  wndclass;
    
    hInst = hInstance;

    // Define class features
    wndclass.cbSize        = sizeof (wndclass);
    wndclass.style         = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc   = WndProc;

    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = 0;
    wndclass.hInstance     = hInstance;

    wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
    wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW);

    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = szAppName;
    wndclass.hIconSm       = LoadIcon (NULL, IDI_APPLICATION);

    // Register the class with Windows
    RegisterClassEx (&wndclass);

    hwndMain = CreateWindow
                  (szAppName,                       // window class name
                   szCaption,                       // window caption
                   WS_OVERLAPPEDWINDOW,             // window style
                                                    
                   10,                              // x position on screen
                   5,                               // y position on screen
                   608,                             // width
                   440,                             // height
                                                    
                   NULL,                            // parent window handle
                   NULL,                            // window menu handle
                   hInst,                           // program instance handle
                   NULL);                           // creation parameters

    ShowWindow (hwndMain, iCmdShow);
    UpdateWindow (hwndMain);

    settings = new config;

    settings -> downloading = false;
    settings -> cancel = false;

    pagelist = ParseCategories (NULL, settings);    // Get set of categories from file


    settings -> load(pagelist);                     // Get options and page preferences from ini file

                                                    
    status = new statuswnd(settings);               // Create the status window (hidden)

                                                    
    GetOS(settings);                                // Get the operating system

                                                    
    url_splitter_Test();                            // Testing stub


    while (GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }
    return msg.wParam;
}


LRESULT CALLBACK WndProc
    (HWND hwndMain, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc;        
    PAINTSTRUCT ps;
    int         loop;                   // Loop variable

    int         butWid, butHei, butGap; // Button width, height, and gap

    int         butScaler, checkScaler; // Scaler to make buttons or checks invisible

    struct tm   *datetime;
    time_t      lTime;
    char        szTime[100];
    char        blank[10];
                                        
    static int WinBorderLR,             // Border between items and left/right edges

               WinBorderTB;             // Border between items and top/bottom edges

                                        
    static RECT rectTitle,              // Title rectangle

                rectHeading;            // Heading rectangle


    switch (iMessage)
    {
        case WM_TIMER:

            time (&lTime);
            datetime = localtime (&lTime);

            // if TIME REACHED

            
            strcpy(szTime, itoa(HOUR, blank, 10)); strcat(szTime, ":");
            strcat(szTime, itoa(MIN, blank, 10)); strcat(szTime, ":");
            strcat(szTime, itoa(SEC, blank, 10));

            if ( (HOUR == settings -> sleep_hrs) &&
                 (MIN == settings -> sleep_mins) )
            {
                KillTimer (hwndMain, 1);

                settings -> save(pagelist);         // Save options in case it crashes!

                settings -> unsupervised = true;    // The download is unsupervised

                get_all_pages(pagelist, settings, status, hButtons[3]);
            }

            return 0;

        case WM_CREATE:

            #if !COMPILER_V6

            lpfnAboutDlgProc   = MakeProcInstance((FARPROC) AboutDlgProc,   hInst);
            lpfnOptionsDlgProc = MakeProcInstance((FARPROC) OptionsDlgProc, hInst);
            #endif


            // Create the buttons and check boxes
            for (loop=0; loop<10; loop++)
            {
                // Create buttons - identifiers 0-9

                hButtons[loop] = CreateWindow
                    ("button",        // window class name
                     NULL,            // window caption
                     WS_CHILD |       // window style
                     WS_VISIBLE |
                     WS_BORDER |
                     BS_PUSHBUTTON,
                     0, 0, 0, 0,      // Pos and Size defined later
                     hwndMain,        // parent window handle
                     (HMENU)loop,     // Button identifier
                     hInst,           // program instance handle
                     NULL);           // creation parameters


                // Create check boxes - identifiers 10-19

                // NOTE - The last check box is never used -

                //        the back button is there instead

                hChecks[loop] = CreateWindow
                    ("button",        // window class name

                     NULL,            // window caption

                     WS_CHILD |       // window style

                     WS_VISIBLE |
                     BS_AUTOCHECKBOX,
                     0, 0, 0, 0,      // Pos and Size defined later

                     hwndMain,        // parent window handle

                     (HMENU)(loop+10),// Check box identifier

                     hInst,           // program instance handle

                     NULL);           // creation parameters


                // Re-direct to new function (subclass) and store old function

                #if COMPILER_V6

                OldButProc = (WNDPROC) SetWindowLong (hButtons[loop],
                                                GWL_WNDPROC, (long) NewButtonProc);
                OldCheckProc = (WNDPROC) SetWindowLong (hChecks[loop],
                                                GWL_WNDPROC, (long) NewCheckProc);
                #else

                OldButProc = (FARPROC) SetWindowLong (hButtons[loop],
                                                GWL_WNDPROC, (long) NewButtonProc);
                OldCheckProc = (FARPROC) SetWindowLong (hChecks[loop],
                                                GWL_WNDPROC, (long) NewCheckProc);
                #endif

            }

            // Get the values to put onto the buttons

            mbuttons.Set_Buttons (hButtons, hChecks, pagelist);
            
            SetFocus (hButtons[0]); // set focus to first button

            ButtonFocus = 0;

            return 0;

        case WM_SETFOCUS:
            // Ensure one of the buttons or check boxes always has the focus

            if (!mbuttons.AtLeaves())
                SetFocus(hButtons[ButtonFocus]);    // set focus to relevant button

            else
                SetFocus(hChecks[ButtonFocus]);     // set focus to relevant check box

            
            return 0;

        case WM_SIZE:

            WinMaWid = LOWORD(lParam);
            WinMaHei = HIWORD(lParam);

            // Set positions of objects in client area


            WinBorderLR        = (int)(WinMaWid * 0.03);
            WinBorderTB        = (int)(WinMaHei * 0.05);
            
            // Alter positions to make either buttons or check boxes visible

            if (!mbuttons.AtLeaves())
            {
                butScaler          = 1;
                checkScaler        = -1;
            }
            else
            {
                butScaler          = -1;
                checkScaler        = 1;
            }

            rectTitle.left     = WinBorderLR;
            rectTitle.right    = WinMaWid - WinBorderLR;
            rectTitle.top      = WinBorderTB;
            rectTitle.bottom   = (int)(WinMaHei * 0.15 + WinBorderTB);
            rectHeading.left   = WinBorderLR;
            rectHeading.right  = WinMaWid - WinBorderLR;
            rectHeading.top    = (int)(rectTitle.bottom + 10);
            rectHeading.bottom = (int)(WinMaHei * 0.1 + rectTitle.bottom + 10);

            butWid = (int)(WinMaWid * 0.46);
            butHei = (int)(WinMaHei * 0.1);
            butGap = (int)(WinMaHei * 0.025);

            // Put the buttons in the correct places

            for (loop=0; loop<5; loop++)
            {
                MoveWindow( hButtons[loop*2],                                        // handle

                            WinBorderLR * butScaler,                                 // left x pos

                            (int)(rectHeading.bottom + 10 + (butHei + butGap)*loop), // top y pos

                            butWid * butScaler,                                      // width

                            butHei,                                                  // height

                            TRUE);
                MoveWindow( hButtons[loop*2+1],                                      // handle

                            (WinMaWid - WinBorderLR - butWid) * butScaler,           // left x pos

                            (int)(rectHeading.bottom + 10 + (butHei + butGap)*loop), // top y pos

                            butWid * butScaler,                                      // width

                            butHei,                                                  // height

                            TRUE);
                MoveWindow( hChecks[loop*2],                                         // handle

                            WinBorderLR * checkScaler,                               // left x pos

                            (int)(rectHeading.bottom + 10 + (butHei + butGap)*loop), // top y pos

                            butWid * checkScaler,                                    // width

                            butHei,                                                  // height

                            TRUE);
                MoveWindow( hChecks[loop*2+1],                                       // handle

                            (WinMaWid - WinBorderLR - butWid) * checkScaler,         // left x pos

                            (int)(rectHeading.bottom + 10 + (butHei + butGap)*loop), // top y pos

                            butWid * checkScaler,                                    // width

                            butHei,                                                  // height

                            TRUE);
            }
            // Make sure the back button is always in it's correct position

            MoveWindow( hButtons[9],                                             // handle

                        WinMaWid - WinBorderLR - butWid,                         // left x pos

                        (int)(rectHeading.bottom + 10 + (butHei + butGap)*4),    // top y pos

                        butWid,                                                  // width

                        butHei,                                                      // height

                        TRUE);
            // Make sure the last check box is never visible

            MoveWindow( hChecks[9],                                              // handle

                        (WinMaWid - WinBorderLR - butWid) * -1,                  // left x pos

                        (int)(rectHeading.bottom + 10 + (butHei + butGap)*9),    // top y pos

                        butWid * -1,                                             // width

                        butHei,                                                  // height

                        TRUE);


            for (loop=0; loop<10; loop++)
            {
                if (strlen(mbuttons.szButtonValue[loop]) == 0)
                {
                    ShowWindow(hButtons[loop], SW_HIDE);
                    ShowWindow(hChecks[loop], SW_HIDE);
                }
                else
                {
                    ShowWindow(hButtons[loop], SW_SHOWNORMAL);
                    ShowWindow(hChecks[loop], SW_SHOWNORMAL);
                }
            }
            // Hide the "Get news now" button while downloading

            if (settings != NULL)
                if ((settings -> downloading) && (mbuttons.MenuLevel() == 0))
                    ShowWindow(hButtons[3], SW_HIDE);

            return 0;

        case WM_KEYDOWN:

            if (wParam-112 == 10)   // F10 key pressed

                return 0;

            // Process function keys F1 to F9

            if (!mbuttons.AtLeaves())
            {
                if ((wParam-112 >= 0) && (wParam-112 < 9))
                    SendMessage (hwndMain, WM_COMMAND, wParam-112, NULL);
            }
            else
            {
                if ((wParam-112 >= 0) && (wParam-112 < 9))
                {
                    if (strlen(mbuttons.szButtonValue[wParam-112]) != 0)
                    {
                        SendMessage (hChecks[wParam-112], WM_LBUTTONDOWN, NULL, NULL);
                        SendMessage (hChecks[wParam-112], WM_LBUTTONUP, NULL, NULL);
                    }
                }
            }
            
            if (wParam == VK_ESCAPE)
                SendMessage (hwndMain, WM_COMMAND, 9, NULL);

            return 0;

        case WM_PAINT:

            // Paint objects on the screen

            hdc = BeginPaint (hwndMain, &ps);

            // Draw rectangle around the title

            RoundRect(hdc, rectTitle.left , rectTitle.top,
                           rectTitle.right, rectTitle.bottom, 12, 12);
            // Set text to text color as set in control panel

            SetTextColor(hdc, COLOR_WINDOWTEXT);
            // Draw Title

            SetBkMode(hdc, OPAQUE);
            SelectObject(hdc, CreateTitleFont);
            DrawText(hdc, szCaption, strlen(szCaption), &rectTitle,
                        DT_CENTER | DT_VCENTER | DT_SINGLELINE );
            // Draw Heading

            SetBkMode(hdc, TRANSPARENT);
            SelectObject(hdc, GetStockObject(SYSTEM_FONT));
            DrawText(hdc, mbuttons.szHeading, strlen(mbuttons.szHeading), &rectHeading,
                        DT_VCENTER | DT_SINGLELINE );
            // End painting

            DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
            EndPaint (hwndMain, &ps);
            return 0;

        case WM_COMMAND:
            if (mbuttons.MenuLevel() == 0)
            {
                switch (LOWORD(wParam)) // Actions caused by buttons or function keys

                {
                case 0: Instructions(); break;
                case 1: if (pagelist != NULL)
                        {
                            mbuttons.PickCategory(0, hChecks, pagelist);        // change to new menu

                            mbuttons.Set_Buttons(hButtons, hChecks, pagelist);  // set button values

                            SetFocus(hButtons[0]);                      // set focus to first button

                            ButtonFocus = 0;
                            SetFocus(hwndMain);
                            // Force windows to redraw the client area

                            SendMessage ( hwndMain, WM_SIZE, 0, MAKELONG(WinMaWid, WinMaHei) );
                            InvalidateRect( hwndMain, NULL, TRUE ); // Make sure window is re-painted

                        }
                        else
                            MessageBox(hwndMain, "You need to download the category file first (F6)", "WNS", MB_OK);
                        break;
                case 2: ShowWindow(hwndMain, SW_MINIMIZE);
                        SetTimer(hwndMain, 1, 5000, NULL);
                        break;
                case 3: if (MessageBox(hwndMain, "This may take a few minutes! Click OK to continue, or 'Cancel' to cancel.",
                            "Note", MB_OKCANCEL | MB_ICONWARNING ) == IDOK)
                        {
                            settings -> save(pagelist);         // Save options in case it crashes!

                            status -> activate();               // Make the status window visible

                            settings -> unsupervised = false;   // The download is not unsupervised

                            get_all_pages(pagelist, settings, status, hButtons[3]);
                        }
                        break;
                case 4: OpenBrowser(); break;
                case 5: // Get new page file from server

                        DialUp(settings);
                        if (!Download_Page_File(settings))
                        {
                            MessageBox(hwndMain, "Cannot get page file from server",
                                "Error!", MB_OK);
                        }
                        // Get new set of categories from file

                        else
                        {
                            settings -> save(pagelist);
                            pagelist = ParseCategories(pagelist, settings);
                            settings -> load(pagelist);
                            MessageBox(hwndMain, "Done! The new categories should now be available.", "WNS", MB_OK);
                        }
                        HangUp( settings );
                        break;
                #if COMPILER_V6

                case 6: DialogBox(hInst, "Options", hwndMain, OptionsDlgProc); break;
                case 7: DialogBox(hInst, "About", hwndMain, AboutDlgProc); break;
                #else

                case 6: DialogBox(hInst, "Options", hwndMain, lpfnOptionsDlgProc); break;
                case 7: DialogBox(hInst, "About", hwndMain, lpfnAboutDlgProc); break;
                #endif          

                case 9:SendMessage (hwndMain, WM_DESTROY, NULL, NULL); break;
                }
            }
            else if ((LOWORD(wParam)>=0) && (LOWORD(wParam)<10))
            {
                mbuttons.PickCategory(LOWORD(wParam), hChecks, pagelist);   // move to new menu

                mbuttons.Set_Buttons(hButtons, hChecks, pagelist);          // set new button values

                ButtonFocus = 0;
                SetFocus(hwndMain);
                if (!mbuttons.AtLeaves())
                    SetFocus(hButtons[0]);                                  // set focus to first button

                else
                    SetFocus(hChecks[0]);                                   // set focus to first check box

                // Force windows to redraw the client area

                SendMessage ( hwndMain, WM_SIZE, 0, MAKELONG(WinMaWid, WinMaHei) );
                InvalidateRect( hwndMain, NULL, TRUE ); // Make sure window is re-painted


            }
            return 0;

        case WM_DESTROY :
            // Application has been killed!!

            if (MessageBox(hwndMain, "Quit - Are you sure?", "Confirm",
                MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2 ) == IDYES)
            {
                settings -> save(pagelist); // Save options before exiting

                KillTimer(hwndMain, 1);     // Stop the timer
                delete status;              // Remove the status window object

                delete settings;            // Remove the settings object

                delete pagelist;            // Remove the page list object

                PostQuitMessage (0);
                return 0;
            }
    }

    return DefWindowProc
              (hwndMain, iMessage, wParam, lParam);
}

// The instructions

void Instructions()
{
    ShellExecute(hwndMain, "open", "Instructions/index.htm", NULL, NULL, SW_SHOWNORMAL);
}

// Open the default windows web browser

void OpenBrowser()
{
    ShellExecute(hwndMain, "open", "Converted Pages/index.htm", NULL, NULL, SW_SHOWNORMAL);
}

void OpenLog()
{
    ShellExecute(hwndMain, "open", "log.txt", NULL, NULL, SW_SHOWNORMAL);
}
    

// Find previous visible button/check box

HWND Set_Prev(int index)
{
    do {
        index--;
        if (index<0) index+=10;
        ButtonFocus = index;
        if (index == 9) return hButtons[9]; // Always allow back button to recieve focus

        if (strlen(mbuttons.szButtonValue[index]) > 0)
            if (!mbuttons.AtLeaves())
                return hButtons[index];
            else
                return hChecks[index];
    } while (index<20); // Endless loop - risky!

    
    return NULL;
}

// Find next visible button/check box

HWND Set_Next(int index)
{
    do {
        index++;
        if (index>9) index-=10;
        ButtonFocus = index;
        if (index == 9) return hButtons[9]; // Always allow back button to recieve focus

        if (strlen(mbuttons.szButtonValue[index]) > 0)
            if (!mbuttons.AtLeaves())
                return hButtons[index];
            else
                return hChecks[index];
    } while (index<20); // Endless loop - risky!


    return NULL;
}

// Sub-Classed windows procedure for buttons

LRESULT CALLBACK NewButtonProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    if (iMsg == WM_KEYDOWN)
        if ((wParam == VK_TAB) || (wParam == VK_DOWN) || (wParam == VK_RIGHT))
        {
            // Pass focus to new button

            if (GetKeyState(VK_SHIFT) < 0) SetFocus( Set_Prev(ButtonFocus) );
            else SetFocus( Set_Next(ButtonFocus) );
            return 0;
        }
        else if ((wParam == VK_UP) || (wParam == VK_LEFT))
        {
            SetFocus( Set_Prev(ButtonFocus) ); // Pass focus to new button

            return 0;
        }
        else if (((wParam-112 >= 0) && (wParam-112 < 9)) || (wParam == VK_ESCAPE))
            SendMessage (hwndMain, WM_KEYDOWN, wParam, lParam);      // Pass key to main window


    return CallWindowProc (OldButProc, hwnd, iMsg, wParam, lParam); // Pass control back

}

// Sub-Classed windows procedure for check boxes

LRESULT CALLBACK NewCheckProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    if (iMsg == WM_KEYDOWN)
        if ((wParam == VK_TAB) || (wParam == VK_DOWN) || (wParam == VK_RIGHT))
        {
            // Pass focus to new button

            if (GetKeyState(VK_SHIFT) < 0) SetFocus( Set_Prev(ButtonFocus) );
            else SetFocus( Set_Next(ButtonFocus) );
            return 0;
        }
        else if ((wParam == VK_UP) || (wParam == VK_LEFT))
        {
            SetFocus( Set_Prev(ButtonFocus) ); // Pass focus to new button

            return 0;
        }
        else if (((wParam-112 >= 0) && (wParam-112 < 9)) || (wParam == VK_ESCAPE))
            SendMessage (hwndMain, WM_KEYDOWN, wParam, lParam);      // Pass key to main window


    return CallWindowProc (OldCheckProc, hwnd, iMsg, wParam, lParam); // Pass control back

}

BOOL CALLBACK AboutDlgProc( HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
    char os_str[100];

    switch (iMsg)
    {
    case WM_INITDIALOG:
        strcpy(os_str, "Detected Operating System: ");
        strcat(os_str, settings -> OS);
        SetDlgItemText(hDlg, OPT_OS, os_str);
        return true;
    case WM_COMMAND:
        switch (LOWORD (wParam))
        {
        case OPT_OK:
            EndDialog( hDlg, 0 );
            return true;
        }
        break;
    }
    return false;
}

BOOL CALLBACK OptionsDlgProc( HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
    char port[10];
    char timeout[10];
    char retries[10];
    static bool use_proxy;
    static bool supervisor;
    static bool show_extern;
    static bool show_status;
    static bool modem;

    switch (iMsg)
    {
    case WM_INITDIALOG:
        SetWindowText
        (GetDlgItem(hDlg, OPT_PROXYADDR), settings -> proxy_addr);

        SetWindowText
        (GetDlgItem(hDlg, OPT_PROXYPORT), itoa(settings -> proxy_port, port, 10) );

        SetWindowText
        (GetDlgItem(hDlg, OPT_TIMEOUT), itoa(settings -> timeout, timeout, 10) );

        SetWindowText
        (GetDlgItem(hDlg, OPT_RETRIES), itoa(settings -> retries, retries, 10) );

        SetWindowText
        (GetDlgItem(hDlg, OPT_FONT), settings -> font_size);

        SetWindowText
        (GetDlgItem(hDlg, OPT_HOURS), settings -> hours);

        SetWindowText
        (GetDlgItem(hDlg, OPT_MINUTES), settings -> minutes);

        use_proxy = settings -> use_proxy;
        SendDlgItemMessage (hDlg, OPT_USEPROXY, BM_SETCHECK,
                            use_proxy, 0L);
        supervisor = settings -> supervisor;
        SendDlgItemMessage (hDlg, OPT_SUPERVISOR, BM_SETCHECK,
                            supervisor, 0L);
        show_extern = settings -> show_extern;
        SendDlgItemMessage (hDlg, OPT_SHOWEXTERN, BM_SETCHECK,
                            show_extern, 0L);
        show_status = settings -> show_status;
        SendDlgItemMessage (hDlg, OPT_SHOWSTATUS, BM_SETCHECK,
                            show_status, 0L);
        modem = settings -> use_modem;
        SendDlgItemMessage (hDlg, OPT_MODEM, BM_SETCHECK,
                            modem, 0L);
        return true;
    case WM_COMMAND:
        switch (LOWORD (wParam))
        {
        case OPT_OK:
            GetWindowText
                (GetDlgItem(hDlg, OPT_PROXYADDR), settings -> proxy_addr, 255);
            GetWindowText
                (GetDlgItem(hDlg, OPT_PROXYPORT), port, 10);
            GetWindowText
                (GetDlgItem(hDlg, OPT_TIMEOUT), timeout, 10);
            GetWindowText
                (GetDlgItem(hDlg, OPT_RETRIES), retries, 10);
            GetWindowText
                (GetDlgItem(hDlg, OPT_FONT), settings -> font_size, 3);
            GetWindowText
                (GetDlgItem(hDlg, OPT_HOURS), settings -> hours, 5);
            GetWindowText
                (GetDlgItem(hDlg, OPT_MINUTES), settings -> minutes, 5);
            
            settings -> proxy_port = atoi( port );
            settings -> use_proxy = use_proxy;
            settings -> supervisor = supervisor;
            settings -> show_extern = show_extern;
            settings -> show_status = show_status;
            settings -> use_modem = modem;
            settings -> timeout = atoi( timeout );
            settings -> retries = atoi( retries );

            settings -> sleep_hrs = atoi( settings -> hours );
            settings -> sleep_mins = atoi( settings -> minutes );

            EndDialog( hDlg, 0 );
            return true;
        case OPT_CANCEL:
            EndDialog( hDlg, 0 );
            return true;
        case OPT_LOG:
            OpenLog();
            return true;
        case OPT_USEPROXY:
            use_proxy = (!use_proxy);
            SendDlgItemMessage (hDlg, OPT_USEPROXY, BM_SETCHECK,
                                use_proxy, 0L);
            return true;
        case OPT_SUPERVISOR:
            supervisor = (!supervisor);
            SendDlgItemMessage (hDlg, OPT_SUPERVISOR, BM_SETCHECK,
                                supervisor, 0L);
            return true;
        case OPT_SHOWEXTERN:
            show_extern = (!show_extern);
            SendDlgItemMessage (hDlg, OPT_SHOWEXTERN, BM_SETCHECK,
                                show_extern, 0L);
            return true;
        case OPT_SHOWSTATUS:
            show_status = (!show_status);
            SendDlgItemMessage (hDlg, OPT_SHOWSTATUS, BM_SETCHECK,
                                show_status, 0L);
            return true;
        case OPT_MODEM:
            modem = (!modem);
            SendDlgItemMessage (hDlg, OPT_MODEM, BM_SETCHECK,
                                modem, 0L);
            return true;
        }
        break;
    }
    return false;
}

syntax highlighted by Code2HTML, v. 0.8.11