|
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;
}
|