* In the past I have found that C to HTML conversion has introduced some syntax errors. I've had a quick look at this file and it seems okay. But I recommend refering to the source code file if you spot any mistakes.

plot_prime.c


/* Filename : plot_prime.c
 *
 * Draw prime number islands.
 *
 * Author       : Craig Dunn
 * Email        : craig@craigsarea.com
 * Website      : www.craigsarea.com
 * Date Created : 16 February 2005
 *
 * No guarantee is given with this code.  Use it at your own risk.
 *****************************************************************/
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <stdio.h>
#include <string.h>
#include "plot_primeres.h"


typedef unsigned char   U8;
typedef unsigned short  U16;
typedef unsigned int    U32;

typedef int             S32;


#define DEF_ORIGIN_X    100
#define DEF_ORIGIN_Y    100

#define DEF_WIDTH       1024
#define DEF_HEIGHT      768

#define BG_RED          32
#define BG_GREEN        32
#define BG_BLUE         135

#define UPDATE_INTERVAL 10000


/* Global Variables.
 *****************************************************************/
HINSTANCE  hInst;
HWND       hwndMain;
U8         *buffer;
HDC        temp_dc;
HBITMAP    bitmap;
HBITMAP    old_bitmap;
HANDLE     finished_event;
HANDLE     draw_event;
HANDLE     plot_event;
char       prime_list[MAX_PATH];
U32        width;
U32        height;
U32        old_height;
S32        origin_x;
S32        origin_y;


/* Function Prototypes.
 *****************************************************************/
int              GetFileName  (char *buffer, int buflen, BOOL b_open);
void             plot         (char *prime_list);
void             save_image   (char *filename);
BOOL             init_plot    (void);
LRESULT CALLBACK MainWndProc  (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
LRESULT CALLBACK DlgSizeProc  (HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam);


/* Function : GetFileName
 *
 * Open either a save as or a load dialog box.
 *****************************************************************/
int GetFileName(char *buffer, int buflen, BOOL b_open)
{
    char tmpfilter[40];
    int i = 0;
    OPENFILENAME ofn;

    memset(&ofn,0,sizeof(ofn));
    ofn.lStructSize  = sizeof(ofn);
    ofn.hInstance    = GetModuleHandle(NULL);
    ofn.hwndOwner    = GetActiveWindow();
    ofn.lpstrFile    = buffer;
    ofn.nMaxFile     = buflen;
    
    if(b_open)
        ofn.lpstrTitle   = "Open";
    else
        ofn.lpstrTitle   = "Save";
        
    ofn.nFilterIndex = 2;
    ofn.lpstrDefExt  = "txt";
    strcpy(buffer,"*.txt");
    ofn.Flags       = 539678;
    ofn.lpstrFilter = NULL;
    
    if(b_open)
        return GetOpenFileName(&ofn);
    else
        return GetSaveFileName(&ofn);
}

/* Function : plot
 *
 * Performs a mod on the prime number list and then updates a 
 * height map.
 *
 * This function can take a little while to complete.  To allow
 * the height map to be drawn to the screen while the ploting is 
 * taking place, this function is run as a seperate thread.  
 *****************************************************************/
void plot(char *prime_list)
{
    FILE *fptr;
    int  x, y;
    U32  prime;
    char string[100];
    U32  count;
    HDC  hdc;
    
    ResetEvent(finished_event);
    ResetEvent(draw_event);

    x = origin_x;
    y = origin_y;

    count = 0;

    /* Check the buffers are okay. */
    if(buffer == NULL || temp_dc == NULL)
    {
        MessageBox(NULL, "The buffers are null!", "Disaster", MB_OK);
        return;
    }    
    

    /* Open the list of prime numbers. */
    fptr = fopen(prime_list, "rb");
    if(fptr == NULL)
    {
        MessageBox(NULL, "Couldn't open the prime number list!", "Disaster", MB_OK);
        return;
    }

    SetWindowText(hwndMain, "Plotting...");

    /* Keep reading prime numbers from the list until the end of file
       is reached. */
    while(!feof(fptr))
    {
        fscanf(fptr, "%s", string);

        prime = atoi(string);

        /* Do the mod and move accordingly. */
        switch(prime % 5)
        {
            case 1:    y-=1;    break;
            case 2:    x+=1;    break;
            case 3:    y+=1;    break;
            case 4:    x-=1;    break;
            default:            break;
        }

        /* If the mod location is still on the screen, plot it. */
        if((y >= 0 && y < height) && (x >= 0 && x < width))
        {
             /* Each height point is only 8 bits.  So, don't
               overflow. */
            if(buffer[x + (y * width)] < 255)
            {
                buffer[x + (y * width)]++;            
                
                /* Draw the height in a shade of green. */
                SetPixel(temp_dc, x, y, RGB(0, buffer[x + (y * width)], 0));
            }
        }
        

        /* Update the screen each time a certain number of primes
           has been read. */
        count++;
        if(count >= UPDATE_INTERVAL)
        {
            count = 0;
            SetEvent(draw_event);
            ResetEvent(plot_event);
            InvalidateRect(hwndMain, NULL, FALSE);
            
            WaitForSingleObject(plot_event, INFINITE);
        }
    }

    SetWindowText(hwndMain, "Plot Prime");
    
    SetEvent(finished_event);

    fclose(fptr);

    InvalidateRect(hwndMain, NULL, FALSE);
}


/* Function : save_image
 *
 * Save the height map image to a bitmap file.
 *****************************************************************/
void save_image(char *filename)
{
    BITMAPFILEHEADER bmp_file_header;
    BITMAPINFOHEADER bmp_info_header;
    RGBQUAD rgb_quad;
    FILE *file_ptr;
    U8 g;
    U32 x, y;

    /* Open the destination file. */
    file_ptr = fopen(filename, "wb");
    if(file_ptr == NULL)
    {
          MessageBox(NULL, "Couldn't open the destination file!", "Disaster", MB_OK);
         return;
    }

    /* Setup the file header. */
    bmp_file_header.bfType    = ('M' << 8) + 'B';
    bmp_file_header.bfSize    = width * height;
    bmp_file_header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER ) + (256 * sizeof(RGBQUAD));

    /* Setup the info header. */
    bmp_info_header.biSize          = sizeof(BITMAPINFOHEADER );
    bmp_info_header.biWidth         = width;
    bmp_info_header.biHeight        = height;
    bmp_info_header.biPlanes        = 1;
    bmp_info_header.biBitCount      = 8;
    bmp_info_header.biCompression   = BI_RGB;
    bmp_info_header.biSizeImage     = 0;
    bmp_info_header.biXPelsPerMeter = 0;
    bmp_info_header.biYPelsPerMeter = 0;
    bmp_info_header.biClrUsed       = 0;
    bmp_info_header.biClrImportant  = 0;

    fwrite(&bmp_file_header, sizeof(BITMAPFILEHEADER), 1, file_ptr);
    fwrite(&bmp_info_header, sizeof(BITMAPINFOHEADER), 1, file_ptr);

    /* Write the palette. */
    rgb_quad.rgbRed      = 32;
    rgb_quad.rgbGreen    = 32;
    rgb_quad.rgbBlue     = 135;
    rgb_quad.rgbReserved = 0;

    fwrite(&rgb_quad, sizeof(RGBQUAD), 1, file_ptr);

    for(g=0; g < 255; g++)
    {
        rgb_quad.rgbRed      = 0;
        rgb_quad.rgbGreen    = g + 1;
        rgb_quad.rgbBlue     = 0;
        rgb_quad.rgbReserved = 0;

        fwrite(&rgb_quad, sizeof(RGBQUAD), 1, file_ptr);
    }

    
    /* Draw the horizontal origin line. */
    memset(&buffer[width * origin_y], 1, width);

    
    /* Draw the vertical origin line. */
    for(y=0; y < height; y++)
        buffer[(width * y) + origin_x] = 1;

        
    /* Write the height map to the BMP file.  Bitmaps are stored
       upside down. */
    for(y=height; y > 0; y--)
    {
        fwrite(&buffer[width * (y-1)], width, 1, file_ptr);    
    }

    fclose(file_ptr);
}


/* Function : init_plot
 *
 * Because the size of the height map can change the setup maybe
 * repeated several times.
 *****************************************************************/
BOOL init_plot(void)
{
    int       y;
    RECT      rect;
    HBRUSH    brush;
    HDC       hdc;
    
      /* Free any previous buffers. */
      if(buffer != NULL)
     {
         free(buffer);
         buffer = NULL;
     }
     
     /* Check the width and height are valid. */
     if(width == 0 || height == 0)
     {
          MessageBox(NULL, "The width or height is set to zero!", "Disaster", MB_OK);
          return FALSE;
     }
     
     /* Create the new buffer. */
     buffer = (U8*)calloc(width * height * sizeof(U8), sizeof(U8));
     if(buffer == NULL)
     {
          MessageBox(NULL, "Can't allocate the buffer!", "Disaster", MB_OK);
          return FALSE;
     }
    
     /* Delete any previous screen buffers. */
     if(temp_dc != NULL)
     {
         SelectObject(temp_dc, old_bitmap);
         DeleteObject(bitmap);
         DeleteDC(temp_dc);
     }
             
        
     /* Create an off screen buffer for the drawing. */
     hdc        = GetDC(hwndMain);
     temp_dc    = CreateCompatibleDC(hdc);
     bitmap     = CreateCompatibleBitmap(hdc, width, height);
     old_bitmap = SelectObject(temp_dc, bitmap);
     ReleaseDC(hwndMain, hdc);

    
     /* Set the background colour. */
     brush = CreateSolidBrush(RGB(BG_RED, BG_GREEN, BG_BLUE));

     rect.top    = 0;
     rect.bottom = height;
     rect.left   = 0;
     rect.right  = width;

     FillRect(temp_dc, &rect, brush);        

             
     /* Draw the 2 origin lines. */
     MoveToEx(temp_dc, origin_x, 0, NULL);
     LineTo(temp_dc, origin_x, height);

     MoveToEx(temp_dc, 0, origin_y, NULL);
     LineTo(temp_dc, width, origin_y);
                          
     DeleteObject(brush);  
     
     GetWindowRect(hwndMain, &rect);
     
     SetScrollRange(hwndMain, SB_HORZ, 0, width - (rect.right), TRUE);
     SetScrollRange(hwndMain, SB_VERT, 0, height - (rect.bottom), TRUE);  
     
     return TRUE;
}


/* Message handler for the size dialog box.
 *****************************************************************/
LRESULT CALLBACK DlgSizeProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
{
     switch(msg)
    {
        case WM_INITDIALOG:
             SetDlgItemInt(hDlg, IDE_WIDTH,  width,  FALSE);
             SetDlgItemInt(hDlg, IDE_HEIGHT, height, FALSE);
             
             SetDlgItemInt(hDlg, IDE_ORIGINX, origin_x, TRUE);
             SetDlgItemInt(hDlg, IDE_ORIGINY, origin_y, TRUE);
             break;
             
        case WM_COMMAND:
             switch(LOWORD(wParam))
             {
                      case IDOK:
                        width  = GetDlgItemInt(hDlg, IDE_WIDTH,  NULL, FALSE);
                        height = GetDlgItemInt(hDlg, IDE_HEIGHT, NULL, FALSE);
                        
                        origin_x = GetDlgItemInt(hDlg, IDE_ORIGINX, NULL, TRUE);
                        origin_y = GetDlgItemInt(hDlg, IDE_ORIGINY, NULL, TRUE);
                        
                        
                        init_plot();
                        
                        InvalidateRect(hwndMain, NULL, FALSE);
                        
                        EndDialog(hDlg, LOWORD(wParam));
                        return TRUE;
                        
                        
                    case IDCANCEL:
                        EndDialog(hDlg, LOWORD(wParam));
                        return TRUE;
             }
    }

    return 0;
}


/* The main message hanlder.
 *****************************************************************/
LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    HDC          hdc;
    PAINTSTRUCT  ps;
    DWORD        dwID;
    HANDLE       array[2];
    U32          y;
    char         image_name[MAX_PATH];
    SCROLLINFO   scroll_info;
    static int   scroll_vert_x;
    static int   scroll_vert_y;

    switch(msg) 
    {
         /* Initialise everything. */
         case WM_CREATE:
             old_height = DEF_HEIGHT;
             height     = DEF_HEIGHT;
             width      = DEF_WIDTH;
             
             origin_x = DEF_ORIGIN_X;
             origin_y = DEF_ORIGIN_Y;
             
             scroll_vert_x = 0;
             scroll_vert_y = 0;
             
             temp_dc = NULL;
             buffer  = NULL;
             
             finished_event = CreateEvent(NULL, TRUE, TRUE, NULL);
             draw_event     = CreateEvent(NULL, TRUE, TRUE, NULL);
             plot_event     = CreateEvent(NULL, TRUE, TRUE, NULL);
             
             init_plot();  
             break;

         
        /* Handle the menu. */
        case WM_COMMAND:
             switch(wParam)
             {
                    case IDM_NEW:
                         init_plot();
                         InvalidateRect(hwndMain, NULL, FALSE);                       
                         break;
                       
                    case IDM_PLOT:
                         CreateThread(NULL, 0, plot, prime_list, 0, &dwID);
                         break;
                       
                  case IDM_OPEN:
                         GetFileName(prime_list, MAX_PATH, TRUE);
                         break;
                       
                    case IDM_SAVE:
                         if(GetFileName(image_name, MAX_PATH, FALSE) != 0)
                              save_image(image_name);
                         break;
                       
                  case IDM_SETUP:
                         DialogBox(hInst, MAKEINTRESOURCE(DLG_SIZE), hwndMain, (DLGPROC)DlgSizeProc);
                         break;
                       
                   case IDM_EXIT:
                         PostMessage(hwnd,WM_CLOSE,0,0);
                         break;
             }
             break;
             
             
        case WM_SIZE:
             SetScrollRange(hwndMain, SB_HORZ, 0, width  - LOWORD(lParam), TRUE);
             SetScrollRange(hwndMain, SB_VERT, 0, height - HIWORD(lParam), TRUE);  
             break;
             
             
        case WM_HSCROLL:
             scroll_info.cbSize = sizeof(SCROLLINFO);
             scroll_info.fMask  = SIF_TRACKPOS;
             GetScrollInfo(hwndMain, SB_HORZ, &scroll_info);
        
             SetScrollPos(hwndMain, SB_HORZ, scroll_info.nTrackPos, TRUE);
             
             scroll_vert_x = scroll_info.nTrackPos;
             
             InvalidateRect(hwndMain, NULL, FALSE);
             break;
              
              
        case WM_VSCROLL:
             scroll_info.cbSize = sizeof(SCROLLINFO);
             scroll_info.fMask  = SIF_TRACKPOS;
             GetScrollInfo(hwndMain, SB_VERT, &scroll_info);
        
             SetScrollPos(hwndMain, SB_VERT, scroll_info.nTrackPos, TRUE);
             
             scroll_vert_y = scroll_info.nTrackPos;
             
             InvalidateRect(hwndMain, NULL, FALSE);
             break;
             
             
        /* Draw to the screen. */
        case WM_PAINT:
             BeginPaint(hwnd, &ps);
             hdc = GetDC(hwnd);

             array[0] = finished_event;
             array[1] = draw_event;
             
             if(WaitForMultipleObjects(2, array, FALSE, 1) != WAIT_TIMEOUT)
             {         
                   BitBlt(hdc, 0, 0, width, height, temp_dc, scroll_vert_x, scroll_vert_y, SRCCOPY);
                   ResetEvent(draw_event);
             }
             
             SetEvent(plot_event);


             ReleaseDC(hwnd, hdc);
             EndPaint(hwnd, &ps);
             break;

             
        /* Clean up and exit. */ 
        case WM_DESTROY:
             if(temp_dc != NULL)
             {
                  SelectObject(temp_dc, old_bitmap);
                  DeleteObject(bitmap);
                  DeleteDC(temp_dc);
              }
             
             /* Free any previous buffers. */
             if(buffer != NULL)
              {                   
                 free(buffer);
                 buffer = NULL;
              }
             
             PostQuitMessage(0);
             break;
             
             
        default:
             return DefWindowProc(hwnd,msg,wParam,lParam);
    }

    return 0;
}


/* Main entry point.
 *****************************************************************/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
{
    MSG msg;
    WNDCLASS wc;

    hInst = hInstance;

    memset(&wc,0,sizeof(WNDCLASS));
    wc.style         = CS_HREDRAW|CS_VREDRAW |CS_DBLCLKS ;
    wc.lpfnWndProc   = (WNDPROC)MainWndProc;
    wc.hInstance     = hInst;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszClassName = "plot_primeWndClass";
    wc.lpszMenuName  = MAKEINTRESOURCE(IDMAINMENU);
    wc.hCursor       = LoadCursor(NULL,IDC_ARROW);
    wc.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
    if (!RegisterClass(&wc))
        return 0;

    hwndMain = CreateWindow("plot_primeWndClass","plot_prime",
        WS_MINIMIZEBOX | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
        WS_MAXIMIZEBOX | WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_THICKFRAME |
        WS_HSCROLL | WS_VSCROLL,
        CW_USEDEFAULT,0,CW_USEDEFAULT,0,
        NULL,
        NULL,
        hInst,
        NULL);

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


BackHome