#ifndef GLOBAL_DECL

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

#endif


void error_page(char*, char*, char*);
void filedelete( void );
void get_all();

// Multi-thread variables:

HANDLE      lock_sema;                  // Global variable lock semaphore

HANDLE      limit_sema;                 // Semaphore to limit the app. to a thread limit

HWND        button;                     // Handle of the get news now button


data_item*  data;                       // Pointer to list item being processed

fileaccess* logfile;                    // Pointer to log file object

config*     settings_a;                 // Pointer to settings object

statuswnd*  status_a;                   // Pointer to status window object

pglist*     pagelist_a;                 // Pointer to page list object

int         thread_count = 0;           // Number of threads running



void initiate()
{
    data_item   *tdata;
    char        url[100];
    char        result[100];
    char        error[100];
    getter*     pagegetter;                 // Pointer to page getter object

    wsock*      connection;                 // Pointer to instance of wsock object


    // Make a separate copy of the page details for the thread to use

    tdata = data;

    // Release lock and allow global variables to be changed

    ReleaseSemaphore(lock_sema, 1, 0);

    connection = new wsock(settings_a);     // Create instance of wsock object


    // Check for errors opening a connection

    if ( connection -> error[0] != NULL )
    {
        strcpy(error, connection -> error);
        error_page(error, "./converted pages/index.htm", NULL);

        logfile -> lock();
        logfile -> write( "ERR! " );
        logfile -> write( error );
        logfile -> unlock();
    }
    else
    {
        strcpy(url, tdata -> url);          // Extract the url from the page details

        pagegetter = new getter(connection, settings_a, logfile, status_a);
        pagegetter -> RetrieveURL(url, result, tdata, 0);
        delete pagegetter;
    }
    
    delete connection;                      // Close connection


    strcpy(tdata -> filename, result);      // Store filename of main page of site


    // Reduce count of running threads, maybe allowing another to begin

    ReleaseSemaphore(limit_sema, 1, 0);
    
    thread_count--;
}

void get_all_pages(pglist* pglist, config* setts, statuswnd* stat, HWND butt)
{
    DWORD       threadID;                   // Thread ID details - not used


    settings_a = setts;
    status_a = stat;
    pagelist_a = pglist;
    button = butt;

    ShowWindow(button, SW_HIDE);            // Hide get news now button


    if (settings_a -> use_modem)
    {
        status_a -> addline("Dialing....");
        
        DialUp(settings_a);
    }

    status_a -> addline("Downloading chosen pages....");

    CreateThread(0, 0, (LPTHREAD_START_ROUTINE)get_all, 0, 0, &threadID);
}

void get_all()
{
    DWORD       threadID;                           // Thread ID details - not used

    fileaccess* contents;                           // Pointer to the contents file object

    char        description[100];                   // Description of page to retrieve

    bool        page_got = false;                   // Has a page been selected yet?

    char        category_str[MAX_CAT_LEVELS * 52];  // Concatenated category values

    char        prev_cat_str[MAX_CAT_LEVELS * 52];  // Previous concatenated category values

    
    prev_cat_str[0] = NULL;

    settings_a -> downloading = true;
    settings_a -> cancel = false;
    
    // Initialise semaphores

    lock_sema   = CreateSemaphore( 0, 0, 1, 0 );
    limit_sema  = CreateSemaphore( 0, MAX_THREADS, MAX_THREADS, 0 );

    // Create an output file for the contents page

    contents = new fileaccess( "./converted pages/index.htm", "w", settings_a );

    // Create an output file for the log

    logfile = new fileaccess( "log.txt", "w", settings_a );

    if (!((contents -> error) || (logfile -> error))) // Error opening files

    {
        logfile -> alwaysflush();
        logfile -> write( "\nLog file for web news speak - " );
        logfile -> writetime();

        logfile -> write( "\n\n\nDeleting old html files." );
        filedelete();                           // Delete old pages

        
        // Write HTML headers

        contents -> write( "<HTML>\n" );
        contents -> write( "<BODY>\n<TITLE>Web News Speak - Contents</TITLE>\n<FONT SIZE=\"");
        contents -> write( settings_a -> font_size );
        contents -> write( "\"><B>" );
        contents -> write( settings_a -> version_number );
        contents -> write( "<BR>Downloaded: " );
        contents -> writetime();
        contents -> write( "<BR><BR>Contents:</B><BR><BR>" );
        
        logfile -> write( "\nSearching page database..\n" );
        logfile -> write( "\nType " );
        logfile -> write( "Site Title  ", 22 );
        logfile -> write( "   " );
        logfile -> write( "URL", 30 );
        logfile -> write( "Message\n", 29 );

        // Traverse list downloading selected pages

        pagelist_a -> move_first();

        do
        {
            data = pagelist_a -> get_item();

            if (data != NULL)
            {
                if (data -> selected)
                {
                    // Get page details

                    strcpy(description, data -> description);
                    // Make sure there is not more than MAX_THREADS running at once

                    WaitForSingleObject(limit_sema, INFINITE);
                    // Create a new thread

                    CreateThread(0, 0, (LPTHREAD_START_ROUTINE)initiate, 0, 0, &threadID);
                    thread_count++;
                    // Wait until thread has taken it's parameter values

                    WaitForSingleObject(lock_sema, INFINITE);
                    page_got = true;
                }
            }
        } while (data != NULL);

        // Wait until all threads are complete

        while (thread_count>0);

        // Build up the contents page

        pagelist_a -> move_first();
        do
        {
            data = pagelist_a -> get_item();
            if (data != NULL)
            {
                if (data -> selected)
                {
                    data -> cat_string(category_str);
                    if (strcmp(category_str, prev_cat_str))
                    {
                        contents -> write("<B>");
                        contents -> write(category_str);
                        contents -> write("</B><BR>");
                        strcpy(prev_cat_str, category_str);
                    }
                    contents -> write("&nbsp;&nbsp;&nbsp;<A HREF=\"");
                    contents -> write(data -> filename);
                    contents -> write("\">");
                    contents -> write(data -> description);
                    contents -> write("</A><BR>");
                }
            }
        } while (data != NULL);

        if (!page_got)
            contents -> write("No pages selected for download!<BR>");

        if (settings_a -> cancel)
        {
            contents -> write("<BR>WARNING - The download was cancelled before it was complete!<BR>");
            logfile -> write( "\n\nWARNING - Download Cancelled!" );
        }


        contents -> write( "<BR><A HREF=\"mailto:webnewsspeak@cc.umist.ac.uk?subject=" );
        contents -> write( "Page or link error\">Report errors or dead links</A>\n" );
        contents -> write( "</FONT></B>\n" );
        contents -> write( "</BODY>\n" );
        contents -> write( "</HTML>" );

        logfile -> write( "\n\nFinished downloading - " );
        logfile -> writetime();
    
        if (settings_a -> cancel)
        {
            status_a -> cancelled();
        }
        else
        {
            status_a -> finished();
        }

        settings_a -> downloading = false;
        settings_a -> cancel = false;

        ShowWindow(button, SW_SHOWNORMAL);              // Restore get news now button

        status_a -> deactivate();
        SetFocus(hwndMain);
        HangUp( settings_a );
        // Only inform of completion if supervised

        if ( !settings_a -> unsupervised )
            MessageBox(hwndMain, "Done!", "WNS", MB_OK);
    }

    delete contents;    // Close contents file

    delete logfile;         // Close logfile file

}

void filedelete( void )
{
    WIN32_FIND_DATA FileData; 
    HANDLE hSearch; 
    char szDirPath[MAX_PATH]; 
    char szNewPath[MAX_PATH]; 
    char szHome[MAX_PATH]; 
 
    BOOL fFinished = FALSE;

    GetCurrentDirectory(MAX_PATH, szHome);
    lstrcpy(szDirPath, szHome);
    lstrcat(szDirPath, "\\source pages\\");
    SetCurrentDirectory(szDirPath);
 
    // Start searching for .HTM files in the source pages directory. 

    hSearch = FindFirstFile("*.*", &FileData);
    if (hSearch == INVALID_HANDLE_VALUE) 
        fFinished = true;

    // Delete each .HTM file

    while (!fFinished) 
    { 
        lstrcpy(szNewPath, szDirPath);
        lstrcat(szNewPath, FileData.cFileName); 
        DeleteFile(FileData.cFileName);
 
        if (!FindNextFile(hSearch, &FileData)) 
            if (GetLastError() == ERROR_NO_MORE_FILES) 
                fFinished = TRUE; 
    }

    // Close the search handle.

    FindClose(hSearch);

    fFinished = FALSE;
    lstrcpy(szDirPath, szHome);
    lstrcat(szDirPath, "\\converted pages\\");
    SetCurrentDirectory(szDirPath);
 
    // Start searching for .HTM files in the converted pages directory. 

    hSearch = FindFirstFile("*.*", &FileData); 
    if (hSearch == INVALID_HANDLE_VALUE) 
        fFinished = true;

    // Delete each .HTM file

    while (!fFinished) 
    { 
        lstrcpy(szNewPath, szDirPath);
        lstrcat(szNewPath, FileData.cFileName); 
        DeleteFile(FileData.cFileName);
 
        if (!FindNextFile(hSearch, &FileData)) 
            if (GetLastError() == ERROR_NO_MORE_FILES) 
                fFinished = TRUE; 
    }

    // Close the search handle.

    FindClose(hSearch);

    SetCurrentDirectory(szHome);
}

void error_page(char* error_desc, char* fname, char* url)
{
    fileaccess outfile( fname, "w", settings_a );

    if ( !outfile.error )
    {
        // Write HTML headers

        outfile.writeheaders(url, "ERROR");

        // Write error description and link

        outfile.write( error_desc );
        outfile.write( "<BR><BR>The URL was: <A HREF=\"" );
        outfile.write( url );
        outfile.write( "\">" );
        outfile.write( url );
        outfile.write( "</A>" );

        // Write HTML footers

        outfile.writeerrorfooters();
    }
}

syntax highlighted by Code2HTML, v. 0.8.11