diff visuality.c @ 0:76568becd6d6

Rhope Alpha 2a source import
author Mike Pavone <pavone@retrodev.com>
date Tue, 28 Apr 2009 23:06:07 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/visuality.c	Tue Apr 28 23:06:07 2009 +0000
@@ -0,0 +1,1302 @@
+
+
+#include <stdio.h>
+#include <math.h>
+
+#include "structs.h"
+#include "visuality.h"
+#include "interp.h"
+#include "parser.h"
+#include "saveload.h"
+
+
+#define	NUM_SPRITES	5
+
+
+FILE * outfile;
+
+
+HGLRC		hRC = NULL;
+HDC			hDC = NULL;
+HWND		hWnd = NULL;
+HINSTANCE	hInstance;
+GLuint	glyph_base;
+
+BOOL mouse_left_down=FALSE;
+BOOL mouse_leftstart_down=FALSE;
+int mouse_lastx;
+int mouse_lasty;
+int mouse_curx;
+int mouse_cury;
+int start_wire_worker=-1;
+int start_wire_ionum=-2;
+BOOL start_wire_isinput;
+BOOL checked_mouse_pos=FALSE;
+
+char new_name_buf[256];
+int buf_size=0;
+
+extern char text_buf[256];
+extern int text_buf_size=0;
+
+extern BOOL execute_active;
+
+worker * view_workerlist;
+wire * view_wirelist;
+
+int current_def=0;
+/*
+void save_program(char * filename)
+{
+	worker * aworkerlist;
+	wire * awirelist;
+	FILE * savefile;
+	int def_num, version = 1;
+	savefile = fopen(filename, "wb");
+	if(!savefile)
+		return;
+	deflist[current_def].num_workers = num_workers;
+	deflist[current_def].num_wires = num_wires;
+	fwrite(&version, 4, 1, savefile);
+	fwrite(&num_defs, 4, 1, savefile);
+	fwrite(deflist, sizeof(worker_def), num_defs, savefile);
+	for(def_num = 0; def_num < num_defs; ++def_num)
+	{
+		if(deflist[def_num].workerlist)
+		{
+			fwrite(&def_num, 4, 1, savefile);
+			//fwrite(&(deflist[def_num].num_workers), 4, 1, savefile);
+			fwrite(deflist[def_num].workerlist, sizeof(worker), deflist[def_num].num_workers, savefile);
+			//fwrite(&(deflist[def_num].num_wires), 4, 1, savefile);
+			fwrite(deflist[def_num].wirelist, sizeof(wire), deflist[def_num].num_wires, savefile);
+		}
+	}
+	def_num = -1;
+	fwrite(&def_num, 4, 1, savefile);
+	fclose(savefile);
+}
+
+void load_program(char * filename)
+{
+	char msg[256];
+	worker * aworkerlist;
+	wire * awirelist;
+	FILE * loadfile;
+	int def_num, version;
+	loadfile = fopen(filename, "rb");
+	if(!loadfile)
+	{
+		MessageBox(NULL, "Could not open file","Error",MB_OK);
+		return;
+	}
+	fread(&version, 4, 1, loadfile);
+	if(version != 1)
+	{
+		MessageBox(NULL, "Can't read files of this version.","Error",MB_OK);
+		return;
+	}
+	fread(&num_defs, 4, 1, loadfile);
+	fread(deflist, sizeof(worker_def), num_defs, loadfile);
+	fread(&def_num, 4, 1, loadfile);
+	while(def_num >= 0 && !feof(loadfile))
+	{
+		sprintf(msg, "Reading def %X at %X", def_num, ftell(loadfile));
+		MessageBox(NULL, msg, "debug",MB_OK);
+		deflist[def_num].workerlist = malloc((deflist[def_num].num_workers+512)*sizeof(worker));
+		fread(deflist[def_num].workerlist, sizeof(worker), deflist[def_num].num_workers, loadfile);
+		deflist[def_num].wirelist = malloc((deflist[def_num].num_wires+1024)*sizeof(wire));
+		fread(deflist[def_num].wirelist, sizeof(wire), deflist[def_num].num_wires, loadfile);
+		deflist[def_num].workers_to_wires_up = malloc((deflist[def_num].num_wires+1024)*sizeof(int));
+		deflist[def_num].workers_to_wires_down = malloc((deflist[def_num].num_wires+1024)*sizeof(int));
+		fread(&def_num, 4, 1, loadfile);
+	}
+	fclose(loadfile);
+	view_workerlist = deflist[0].workerlist;
+	view_wirelist = deflist[0].wirelist;
+	num_workers = deflist[0].num_workers;
+	num_wires = deflist[0].num_wires;
+	initpredefworkers();
+	//sprintf(msg,"%d workers, %d wires in %s",deflist[0].num_workers,deflist[0].num_wires,deflist[0].name);
+	//MessageBox(NULL,msg,"visdbg",MB_OK);
+}*/
+
+
+
+BOOL	keys[256];
+BOOL	active = TRUE;
+BOOL	fullscreen=TRUE;
+BOOL	gameover = FALSE;
+
+GLfloat		xrot;								// X Rotation ( NEW )
+GLfloat		yrot;								// Y Rotation ( NEW )
+GLfloat		zrot;								// Z Rotation ( NEW )
+
+GLuint		texture[NUM_SPRITES];							// Storage For One Texture ( NEW )
+float		xsizes[NUM_SPRITES] = {0.75f, 1.0f, 0.25f, 0.25f, 2.0f};
+float		ysizes[NUM_SPRITES] = {1.0f, 0.5f, 0.25f, 0.25f, 2.0f};
+float		xtexturefit[NUM_SPRITES] = {0.75f, 1.0f, 1.0f, 1.0f, 1.0f};
+float		ytexturefit[NUM_SPRITES] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+float		gunxpos = 5.0f;
+char	spritenames[NUM_SPRITES][32] = {"rini.bmp", "zapper.bmp", "heart.bmp", "fireball.bmp", "kiss.bmp"};
+
+#define SCREEN_WIDTH_REL	8.8f
+#define SCREEN_HEIGHT_REL	6.6f
+#define PI 3.14159265
+
+int selected_worker = -1;
+int selected_wire = -1;
+
+
+int killed = 0;
+
+
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+	
+
+AUX_RGBImageRec *LoadBMP(char *Filename)					// Loads A Bitmap Image
+{
+	FILE *File=NULL;							// File Handle
+	if (!Filename)								// Make Sure A Filename Was Given
+	{
+		return NULL;							// If Not Return NULL
+	}
+	File=fopen(Filename,"r");						// Check To See If The File Exists
+	if (File)								// Does The File Exist?
+	{
+		fclose(File);							// Close The Handle
+		return auxDIBImageLoad(Filename);				// Load The Bitmap And Return A Pointer
+	}
+	return NULL;								// If Load Failed Return NULL
+}
+/*
+int LoadGLTextures()								// Load Bitmaps And Convert To Textures
+{
+	int Status=FALSE;							// Status Indicator
+	AUX_RGBImageRec *TextureImage[NUM_SPRITES];					// Create Storage Space For The Texture
+	int i;
+	
+
+	for(i = 0; i < NUM_SPRITES; ++i)
+	{
+		
+		TextureImage[i] = NULL;				// Set The Pointer To NULL
+		// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
+		if (TextureImage[i]=LoadBMP(spritenames[i]))
+		{
+			Status=TRUE;							// Set The Status To TRUE
+			glGenTextures(1, &texture[i]);					// Create The Texture
+	
+			// Typical Texture Generation Using Data From The Bitmap
+			glBindTexture(GL_TEXTURE_2D, texture[i]);
+			// Generate The Texture
+			glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[i]->sizeX, TextureImage[i]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[i]->data);
+			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);	// Linear Filtering
+			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);	// Linear Filtering
+		}
+		if (TextureImage[i])							// If Texture Exists
+		{
+			if (TextureImage[i]->data)					// If Texture Image Exists
+			{
+				free(TextureImage[i]->data);				// Free The Texture Image Memory
+			}
+	
+			free(TextureImage[i]);						// Free The Image Structure
+		}
+		//xsizes[i] = 0.5f;
+		//ysizes[i] = 1.0f;
+	}
+	
+	return Status;								// Return The Status
+}
+
+*/
+
+GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
+{
+	if(height ==0)
+		height = 1;
+	glViewport(0,0,width,height);
+
+	glMatrixMode(GL_PROJECTION);	//Reset projection matrix
+	glLoadIdentity();
+	
+	//Calculate aspect ratio
+	gluPerspective(45.0f, (GLfloat)width/ (GLfloat)height, 0.1f, 100.0f);
+	
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();				//reset modelview matrix
+}
+
+int InitGL(GLvoid)
+{
+	//if (!LoadGLTextures())							// Jump To Texture Loading Routine ( NEW )
+	//{
+	//	return FALSE;							// If Texture Didn't Load Return FALSE ( NEW )
+	//}
+	HFONT font;
+	glEnable(GL_TEXTURE_2D);
+	glShadeModel(GL_SMOOTH);
+	
+	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	//blackness
+	
+	glClearDepth(1.0f);
+	glEnable(GL_DEPTH_TEST);
+	glDepthFunc(GL_LEQUAL);
+	
+	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+	glEnable(GL_COLOR_MATERIAL);
+
+
+	
+	font = CreateFont(-24, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, 
+		ANTIALIASED_QUALITY, FF_SWISS || VARIABLE_PITCH, "Arial");
+	SelectObject(hDC, font);
+
+	glyph_base = glGenLists(224);
+	wglUseFontOutlines(hDC, 32, 224, glyph_base, 0.0, 0.0, WGL_FONT_POLYGONS, NULL);
+	DeleteObject(font);
+	
+	return TRUE;
+}
+
+void drawtriangle(double xpos, double ypos, double width, double height, double angle)
+{
+	if(xpos != 0.0 || ypos != 0.0)
+		glTranslatef(xpos, ypos, 0.0);
+	
+	if(angle != 0.0)
+		glRotatef(angle, 0.0,0.0,1.0);
+		
+	glBegin(GL_TRIANGLES);
+		glVertex2f(0.0, height/2); //Top
+		glVertex2f(0.0 - width/2, 0.0 - height/2); //Left
+		glVertex2f(width/2, 0.0 - height/2); //Right
+	glEnd();		
+		
+	if(angle != 0.0)
+		glRotatef(0.0-angle, 0.0,0.0,1.0);//restore rotation without loading identity
+	if(xpos != 0.0 || ypos != 0.0)
+		glTranslatef(0.0-xpos, 0.0-ypos, 0.0);
+}
+
+void drawrect(double xpos, double ypos, double width, double height, double angle)
+{
+	if(xpos != 0.0 || ypos != 0.0)
+		glTranslatef(xpos, ypos, 0.0);
+	
+	if(angle != 0.0)
+		glRotatef(angle, 0.0,0.0,1.0);
+		
+	glBegin(GL_QUADS);
+		glVertex2f(0.0 - width/2,  height/2.0); //Top Left
+		glVertex2f(width/2, height/2.0); //Top Right
+		glVertex2f(width/2, 0.0 - height/2.0); //Bottom Right
+		glVertex2f(0.0 - width/2, 0.0 - height/2.0); //Bottom Left
+		
+	glEnd();
+		
+	if(angle != 0.0)
+		glRotatef(0.0-angle, 0.0,0.0,1.0);//restore rotation without loading identity
+	if(xpos != 0.0 || ypos != 0.0)
+		glTranslatef(0.0-xpos, 0.0-ypos, 0.0);
+}
+void drawshapestrip(int shape_type, double length, double ypos, double width, double height, int num)
+{
+	double currentpos, spacing;
+	int i;
+	
+	spacing = length/(double)num;
+	currentpos = 0.0 - length/2.0 + spacing/2.0;
+	for(i = 0; i < num; ++i)
+	{
+		if(shape_type == 0)
+			drawtriangle(currentpos, ypos, width, height, 0.0);
+		else
+			drawrect(currentpos, ypos, width, height, 0.0);
+		currentpos += spacing;
+	}
+}
+
+double get_io_xpos(worker * some_worker, int output_num, BOOL is_input)
+{
+	double length, currentpos, spacing;
+	if(is_input && output_num == -1)
+		return some_worker->xpos + some_worker->width/2.0 + INPUT_SIZE/2.0;
+	if(some_worker->type == 2 && is_input) //Trapezoid
+		length = 2.0*(some_worker->width)/3.0;
+	else
+		length = some_worker->width;
+	fprintf(outfile, "Worker length: %f, worker width: %f\n");
+	if(is_input)
+		spacing = length/(some_worker->num_inputs);
+	else
+		spacing = length/(some_worker->num_outputs);
+	currentpos = some_worker->xpos - length/2.0 + spacing/2.0;
+	return currentpos + spacing * (double)output_num;
+}
+
+double get_io_ypos(worker * some_worker, int output_num, BOOL is_input)
+{
+	if(is_input && output_num != -1)
+		return some_worker->ypos + (some_worker->height)/2.0;
+	else
+		return some_worker->ypos - ((some_worker->height)/2.0);
+}
+
+void drawshape(int shape_type, double xpos, double ypos, double width, double height, double angle, int inputs, int outputs, char *text, BOOL selected)
+{
+	double x, y,temp, currentpos, spacing;
+	double *inputx, *inputy, *outputx, *outputy;
+	double ioangle, hypot;
+	int i;
+	glLoadIdentity();
+	glTranslatef(SCREEN_WIDTH_REL / (-2.0f) + xpos, SCREEN_HEIGHT_REL / (-2.0f) + ypos,-8.0f);
+	xpos = 0.0; ypos = 0.0;
+	glRotatef(angle, 0.0,0.0,1.0);
+	if(selected)
+		glColor3f(SELECT_RED, SELECT_GREEN, SELECT_BLUE);
+	else
+		glColor3f(BODY_RED, BODY_GREEN, BODY_BLUE);
+	switch(shape_type)
+	{
+	case 0: //Triangle
+		drawtriangle(0.0, 0.0, width, height, 0.0);
+		glTranslatef(0.0-width/4.0, 0.0-height/4.0,0);
+		
+		break;
+	case 1: //Rectangle
+		drawrect(0.0, 0.0, width, height, angle);
+		glColor3f(INPUT_RED, INPUT_GREEN, INPUT_BLUE);
+		if(inputs)
+			drawshapestrip(0, width, height/2.0 + INPUT_SIZE/2.0,INPUT_SIZE, INPUT_SIZE, inputs);
+		drawtriangle(xpos + width/2.0 + INPUT_SIZE/2.0, ypos-height/2.0+INPUT_SIZE/2.0, INPUT_SIZE, INPUT_SIZE, 0.0);
+		glColor3f(OUTPUT_RED, OUTPUT_GREEN, OUTPUT_BLUE);
+		if(outputs)
+			drawshapestrip(1, width, 0.0-(height/2.0 + OUTPUT_SIZE/2.0),OUTPUT_SIZE, OUTPUT_SIZE, outputs);
+		glTranslatef(0.0-width/2.0 + width/16.0, 0.0-height/3.0, 0.0);
+		
+		break;
+	case 2: //Trapezoid
+		glBegin(GL_QUADS);
+			glVertex2f(xpos - width/3.0 , ypos + height/2.0); //Top Left
+			glVertex2f(xpos + width/3.0, ypos + height/2.0); //Top Right
+			glVertex2f(xpos + width/2.0, ypos - height/2.0); //Bottom Right
+			glVertex2f(xpos - width/2.0, ypos - height/2.0); //Bottom Left
+		glEnd();
+		glColor3f(INPUT_RED, INPUT_GREEN, INPUT_BLUE);
+		if(inputs)
+			drawshapestrip(0, 2.0*(width/3.0), height/2.0 + INPUT_SIZE/2.0,INPUT_SIZE, INPUT_SIZE, inputs);
+		drawtriangle(xpos + width/2.0 + INPUT_SIZE/2.0, ypos-height/2.0+INPUT_SIZE/2.0, INPUT_SIZE, INPUT_SIZE, 0.0);
+		glColor3f(OUTPUT_RED, OUTPUT_GREEN, OUTPUT_BLUE);
+		if(outputs)
+			drawshapestrip(1, width, 0.0-(height/2.0 + OUTPUT_SIZE/2.0),OUTPUT_SIZE, OUTPUT_SIZE, outputs);
+		glTranslatef(0.0-width/3.0, 0.0-height/3.0, 0.0);
+		break;
+		
+	case 3: //Ellipse
+	
+		x = 3.4587;
+		y = 2293.784;
+		
+		glBegin(GL_TRIANGLE_FAN);
+			glVertex2f(0.0, 0.0);
+			
+			if(inputs)
+			{
+				spacing = width/(double)inputs;
+				currentpos = 0.0-width/2.0 + spacing/2.0;
+				inputx = (double *)malloc(inputs*sizeof(double));
+				inputy = (double *)malloc(inputs*sizeof(double));
+				i = 0;
+			}
+			for(x = 0.0-width/2 ; x <= width/2.0+CIRCLE_STEP; x += CIRCLE_STEP)
+			{
+				y = sqrt(fabs(pow(height/2.0,2) - (pow(height/2.0,2)*pow(x, 2))/pow(width/2.0, 2)));
+				glVertex2f(x, y);
+				if(inputs && x >= currentpos)
+				{
+					inputx[i] = x;
+					inputy[i] = y;
+					++i;
+					currentpos += spacing;
+				}
+			}
+			x -= CIRCLE_STEP;
+			while(x >= 0.0-width/2)
+			{
+				y = 0.0-sqrt(fabs(pow(height/2.0,2) - (pow(height/2.0,2)*pow(x, 2))/pow(width/2.0, 2)));
+				glVertex2f(x+xpos, y+ypos);
+				x -= CIRCLE_STEP;
+			}
+				
+		glEnd();
+			
+		glColor3f(INPUT_RED, INPUT_GREEN, INPUT_BLUE);
+		for(i = 0; i < inputs; ++i)
+		{
+			ioangle = atan2(inputy[i], inputx[i]);
+			hypot = sqrt(pow(inputx[i],2) + pow(inputy[i], 2)) + INPUT_SIZE/2;
+			x = hypot * cos(ioangle);
+			y = hypot * sin(ioangle);
+			ioangle *= (180/PI);
+			fprintf(outfile, "oldx: %f, oldy: %f, newx: %f, newy %f, hypot %f, angle %f\n",inputx[i],inputy[i],x,y,hypot, ioangle);
+			drawtriangle(x,y,INPUT_SIZE,INPUT_SIZE, 90-ioangle);
+		}
+		glTranslatef(0.0-width/8.0, 0.0, 0.0);
+		break;
+	default:
+		break;
+	}
+	if(text)
+	{
+		glColor3f(TEXT_RED, TEXT_GREEN, TEXT_BLUE);
+		glPushAttrib(GL_LIST_BIT);
+			glListBase(glyph_base-32);
+		glScalef(0.25,0.25,0.25);
+		
+		glCallLists(strlen(text),GL_UNSIGNED_BYTE, text);
+	
+		glPopAttrib();
+		
+	}
+}
+
+#define INTX_TO_FLOAT_REL(val)	(((double)val)*SCREEN_WIDTH_REL/640.0)
+#define INTY_TO_FLOAT_REL(val)	(((double)val)*SCREEN_HEIGHT_REL/480.0)
+
+//void drawshape(int shape_type, double xpos, double ypos, double width, double height, double angle, int inputs, int outputs)
+int DrawGLScene(GLvoid)
+{
+	double line_startx;
+	double line_starty;
+	double line_endx;
+	double line_endy;
+	double m,b,x,y,mousey;
+	int i,j;
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	
+	for(i = 0; i < num_workers; ++i)
+	{
+		if(mouse_leftstart_down 
+			&& INTX_TO_FLOAT_REL(mouse_curx) > (view_workerlist[i].xpos - view_workerlist[i].width/2.0) 
+			&& INTX_TO_FLOAT_REL(mouse_curx) < (view_workerlist[i].xpos + view_workerlist[i].width/2.0)
+			&& INTY_TO_FLOAT_REL(mouse_cury) > (view_workerlist[i].ypos - view_workerlist[i].height/2.0) 
+			&& INTY_TO_FLOAT_REL(mouse_cury) < (view_workerlist[i].ypos + view_workerlist[i].height/2.0))
+		{
+			view_workerlist[i].grabbed = TRUE;
+			selected_worker = i;
+			selected_wire = -1;
+			mouse_leftstart_down = FALSE;
+		}
+		else if(mouse_leftstart_down
+			&& INTX_TO_FLOAT_REL(mouse_curx) > (view_workerlist[i].xpos - view_workerlist[i].width/2.0) //Check for mouse in input or output area
+			&& INTX_TO_FLOAT_REL(mouse_curx) < (view_workerlist[i].xpos + view_workerlist[i].width/2.0)
+			&& (INTY_TO_FLOAT_REL(mouse_cury) > (view_workerlist[i].ypos - view_workerlist[i].height/2.0 - OUTPUT_SIZE))
+			&& (INTY_TO_FLOAT_REL(mouse_cury) < (view_workerlist[i].ypos + view_workerlist[i].height/2.0 + INPUT_SIZE)))
+		{
+			if(INTY_TO_FLOAT_REL(mouse_cury) > view_workerlist[i].ypos && view_workerlist[i].num_inputs > 0)//is mouse above or below worker (inputs are above, outputs below)?
+			{
+				fputs("Hit on input region.\n", outfile);
+				for(j = 0; j < view_workerlist[i].num_inputs; ++j)
+				{
+					if(INTX_TO_FLOAT_REL(mouse_curx) > (get_io_xpos(&view_workerlist[i], j, TRUE)-INPUT_SIZE/2.0) && INTX_TO_FLOAT_REL(mouse_curx) < (get_io_xpos(&view_workerlist[i], j, TRUE)+INPUT_SIZE/2.0))
+					{
+						fprintf(outfile, "Hit on input number %d on worker %d.\n", j, i);
+						mouse_leftstart_down = FALSE;
+						if(start_wire_worker >= 0)
+						{
+							fprintf(outfile, "Adding wire %d. output_num: %d, input_num: %d", num_wires,start_wire_ionum, j);
+							//Add wire
+							view_wirelist[num_wires].start_worker = start_wire_worker;
+							view_wirelist[num_wires].end_worker = i;
+							view_wirelist[num_wires].output_num = start_wire_ionum;;
+							view_wirelist[num_wires].input_num = j;
+							++num_wires;
+							start_wire_worker = start_wire_ionum = -1;
+							
+						}
+						else
+						{
+							fputs("Saving information for later wire creation.\n", outfile);
+							start_wire_worker = i;
+							start_wire_ionum = j;
+							start_wire_isinput=TRUE;
+						}
+						break;
+					}
+				}
+			}
+			else if(view_workerlist[i].num_outputs > 0)
+			{
+				fputs("Hit on output region.\n", outfile);
+				for(j = 0; j < view_workerlist[i].num_outputs; ++j)
+				{
+					fprintf(outfile, "Checking mouse x(%f) for hit on output number %d with position %f\n", INTX_TO_FLOAT_REL(mouse_curx), j, get_io_xpos(&view_workerlist[i], j, FALSE));
+					if(INTX_TO_FLOAT_REL(mouse_curx) > (get_io_xpos(&view_workerlist[i], j, FALSE)-OUTPUT_SIZE/2.0) && INTX_TO_FLOAT_REL(mouse_curx) < (get_io_xpos(&view_workerlist[i], j, FALSE)+OUTPUT_SIZE/2.0))
+					{
+						fprintf(outfile, "Hit on output number %d on worker %d.\n", j, i);
+						mouse_leftstart_down = FALSE;
+						if(start_wire_worker >= 0)
+						{
+							fprintf(outfile, "Adding wire %d. output_num: %d, input_num: %d", num_wires, j, start_wire_ionum);
+							//Add wire
+							view_wirelist[num_wires].start_worker = i;
+							view_wirelist[num_wires].end_worker = start_wire_worker;
+							view_wirelist[num_wires].output_num = j;
+							view_wirelist[num_wires].input_num = start_wire_ionum;
+							if(start_wire_ionum == -1)
+								view_workerlist[start_wire_worker].null_input = TRUE;
+							++num_wires;
+							start_wire_worker = start_wire_ionum = -1;
+						}
+						else
+						{
+							fputs("Saving information for later wire creation.\n", outfile);
+							start_wire_worker = i;
+							start_wire_ionum = j;
+							start_wire_isinput=FALSE;
+						}
+						break;
+					}
+				}
+			}
+			
+		}
+		else if(mouse_leftstart_down
+			&& INTX_TO_FLOAT_REL(mouse_curx) > (view_workerlist[i].xpos + view_workerlist[i].width/2.0) //Check for mouse in input or output area
+			&& INTX_TO_FLOAT_REL(mouse_curx) < (view_workerlist[i].xpos + view_workerlist[i].width/2.0+INPUT_SIZE)
+			&& (INTY_TO_FLOAT_REL(mouse_cury) > (view_workerlist[i].ypos - view_workerlist[i].height/2.0))
+			&& (INTY_TO_FLOAT_REL(mouse_cury) < (view_workerlist[i].ypos - view_workerlist[i].height/2.0 + INPUT_SIZE)))
+		{
+			fprintf(outfile, "Click on NULL input at %f,%f\n", INTX_TO_FLOAT_REL(mouse_curx), INTY_TO_FLOAT_REL(mouse_cury));
+			mouse_leftstart_down = FALSE;
+			if(start_wire_worker >= 0)
+			{
+				fprintf(outfile, "Adding wire %d. output_num: %d, input_num: %d", num_wires,start_wire_ionum, -1);
+				//Add wire
+				view_wirelist[num_wires].start_worker = start_wire_worker;
+				view_wirelist[num_wires].end_worker = i;
+				view_wirelist[num_wires].output_num = start_wire_ionum;;
+				view_wirelist[num_wires].input_num = -1;
+				view_workerlist[i].null_input = TRUE;
+				++num_wires;
+				start_wire_worker = start_wire_ionum = -1;
+				
+			}
+			else
+			{
+				fputs("Saving information for later wire creation.\n", outfile);
+				start_wire_worker = i;
+				start_wire_ionum = -1;
+				start_wire_isinput=TRUE;
+			}
+		}
+		else if(mouse_leftstart_down)
+		{
+			fprintf(outfile, "Click at %f,%f, worker at %f,%f with size %f,%f\n", INTX_TO_FLOAT_REL(mouse_curx), INTY_TO_FLOAT_REL(mouse_cury), view_workerlist[i].xpos, view_workerlist[i].ypos, view_workerlist[i].width, view_workerlist[i].height);
+		}
+				
+		if(!mouse_left_down)
+			view_workerlist[i].grabbed= FALSE;
+		if(mouse_left_down && view_workerlist[i].grabbed && (mouse_curx != mouse_lastx || mouse_cury != mouse_lasty))
+		{
+			view_workerlist[i].xpos += INTX_TO_FLOAT_REL(mouse_curx-mouse_lastx);
+			view_workerlist[i].ypos += INTY_TO_FLOAT_REL(mouse_cury-mouse_lasty);
+		}
+		drawshape(view_workerlist[i].display_type, view_workerlist[i].xpos, view_workerlist[i].ypos, view_workerlist[i].width, view_workerlist[i].height, 
+			view_workerlist[i].angle, view_workerlist[i].num_inputs, view_workerlist[i].num_outputs, view_workerlist[i].name, selected_worker==i);
+	}
+	
+
+	glLoadIdentity();
+	glTranslatef(SCREEN_WIDTH_REL / (-2.0f), SCREEN_HEIGHT_REL / (-2.0f),-8.0f);
+
+	glColor3f(WIRE_RED, WIRE_GREEN, WIRE_BLUE);
+	for(i = 0; i < num_wires; ++i)
+	{
+		fprintf(outfile, "Wire %d starts in worker %d at output %d of %d and ends in worker %d at input %d of %d\n", i, view_wirelist[i].start_worker,
+			view_wirelist[i].output_num, view_workerlist[view_wirelist[i].start_worker].num_outputs, view_wirelist[i].end_worker, view_wirelist[i].input_num, view_workerlist[view_wirelist[i].end_worker].num_inputs);
+		line_startx = get_io_xpos(&view_workerlist[view_wirelist[i].start_worker], view_wirelist[i].output_num, FALSE);
+		line_starty = get_io_ypos(&view_workerlist[view_wirelist[i].start_worker], view_wirelist[i].output_num, FALSE)-OUTPUT_SIZE;
+		line_endx = get_io_xpos(&view_workerlist[view_wirelist[i].end_worker], view_wirelist[i].input_num, TRUE);
+		line_endy = get_io_ypos(&view_workerlist[view_wirelist[i].end_worker], view_wirelist[i].input_num, TRUE)+OUTPUT_SIZE;
+		
+		x = INTX_TO_FLOAT_REL(mouse_curx);
+		mousey = INTY_TO_FLOAT_REL(mouse_cury);
+		if(mouse_leftstart_down)
+		{
+			//y = mx=b
+			
+			if(line_startx < line_endx)
+			{
+				if(x >= line_startx && x <= line_endx)
+				{
+					m = (line_endy-line_starty)/(line_endx-line_starty);
+					b = line_starty;
+					x -= line_startx;
+					y = m*x + b;
+					fprintf(outfile, "y: %f, m: %f, x: %f, b: %f, mousey: %f\n", y,m,x,b,mousey);
+					if(mousey >= (y-0.05) && mousey <= (y+0.05))
+					{
+						selected_wire = i;
+						selected_worker = -1;
+					}
+				}
+			} 
+			else if(line_endx > line_startx)
+			{
+				if(x <= line_startx && x >= line_endx)
+				{
+					m = (line_starty-line_endy)/(line_startx-line_endy);
+					b = line_endy;
+					y = m*x + b;
+					x -= line_endx;
+					if(mousey >= (y-0.05) && mousey <= (y+0.05))
+					{
+						selected_wire = i;
+						selected_worker = -1;
+					}
+				}
+			}
+			else	//avoid divide by zero error
+			{
+				if(x >= (line_startx-0.05) && x <= (line_startx+0.05))
+				{
+					if(line_starty > line_endy)
+					{
+						if(mousey >= line_endy && mousey <= line_starty)
+						{
+							selected_wire = i;
+							selected_worker = -1;
+						}
+					}
+					else
+					{
+						if(mousey <= line_endy && mousey >= line_starty)
+						{
+							selected_wire = i;
+							selected_worker = -1;
+						}
+					}
+				}
+			}
+		}
+		if(i == selected_wire)
+			glColor3f(SELECT_RED, SELECT_GREEN, SELECT_BLUE);
+
+		fprintf(outfile, "Start (%f,%f), End (%f, %f), Mouse(%f, %f)\n", line_startx, line_starty, line_endx, line_endy, x, mousey);
+
+		glBegin(GL_QUADS);
+			glVertex2f(line_startx, line_starty);
+			glVertex2f(line_startx+0.1, line_starty);
+			glVertex2f(line_endx+0.1, line_endy);
+			glVertex2f(line_endx, line_endy);
+		glEnd();
+		
+		if(i == selected_wire)
+			glColor3f(WIRE_RED, WIRE_GREEN, WIRE_BLUE);
+	}
+	mouse_leftstart_down = FALSE;
+	//view_workerlist[3].angle += 1.0;
+	checked_mouse_pos=TRUE;
+
+	if(buf_size)
+	{
+		glColor3f(1.0, 1.0, 1.0);
+		glPushAttrib(GL_LIST_BIT);
+		glListBase(glyph_base-32);
+
+		glScalef(0.25,0.25,0.25);
+		
+		glCallLists(buf_size,GL_UNSIGNED_BYTE, new_name_buf);
+	
+		glPopAttrib();
+	}
+/*
+	if(execute_active)
+	{
+		for(i = 0; i < num_workers; ++i)
+			process_worker(i);
+		if(!execute_active)
+		{
+			for(i = 0; i < num_datum; ++i)
+			{
+				if(data[i].type & 0x80)
+					free(data[i].contents);
+			}
+		}
+	}
+*/
+
+	mouse_lastx = mouse_curx;
+	mouse_lasty = mouse_cury;
+
+	return TRUE;
+}
+
+GLvoid KillGLWindow(GLvoid)
+{
+	if(fullscreen)
+	{
+		ChangeDisplaySettings(NULL, 0);
+		ShowCursor(TRUE);
+	}
+	if(hRC)
+	{
+		glDeleteLists(glyph_base, 224);
+		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;
+	}
+}
+
+BOOL CreateGLWindow(char * title, int width, int height, int bits, BOOL fullscreenflag)
+{
+	GLuint	PixelFormat;
+	WNDCLASS	wc;
+	DWORD		dwExStyle;
+	DWORD		dwStyle;
+	
+	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
+		0,								// 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
+	};
+	
+	RECT	WindowRect;
+	WindowRect.left = (long)0;
+	WindowRect.right = (long)width;
+	WindowRect.top = (long)0;
+	WindowRect.bottom=(long)height;
+	
+	fullscreen = fullscreenflag;
+
+	hInstance		= GetModuleHandle(NULL);			// Grab An Instance For Our Window
+	wc.style		= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;		// Redraw On Move, And Own DC For Window
+	wc.lpfnWndProc		= (WNDPROC) WndProc;				// WndProc Handles Messages
+	wc.cbClsExtra		= 0;						// No Extra Window Data
+	wc.cbWndExtra		= 0;						// No Extra Window Data
+	wc.hInstance		= hInstance;					// Set The Instance
+	wc.hIcon		= LoadIcon(NULL, IDI_WINLOGO);			// Load The Default Icon
+	wc.hCursor		= LoadCursor(NULL, IDC_ARROW);			// Load The Arrow Pointer
+	wc.hbrBackground	= NULL;						// No Background Required For GL
+	wc.lpszMenuName		= NULL;						// We Don't Want A Menu
+	wc.lpszClassName	= "OpenGL";					// Set The Class Name
+
+	if (!RegisterClass(&wc))						// Attempt To Register The Window Class
+	{
+		MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
+		return FALSE;							// Exit And Return FALSE
+	}
+
+	if (fullscreen)								// Attempt Fullscreen Mode?
+	{
+		DEVMODE dmScreenSettings;					// Device Mode
+		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));		// Makes Sure Memory's Cleared
+		dmScreenSettings.dmSize=sizeof(dmScreenSettings);		// Size Of The Devmode Structure
+		dmScreenSettings.dmPelsWidth	= width;			// Selected Screen Width
+		dmScreenSettings.dmPelsHeight	= height;			// Selected Screen Height
+		dmScreenSettings.dmBitsPerPel	= bits;				// Selected Bits Per Pixel
+		dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
+		// Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
+		if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
+		{
+
+			// If The Mode Fails, Offer Two Options.  Quit Or Run In A Window.
+			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;				// Select Windowed Mode (Fullscreen=FALSE)
+			}
+			else
+			{
+
+				// Pop Up A Message Box Letting User Know The Program Is Closing.
+				MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
+				return FALSE;					// Exit And Return FALSE
+			}
+		}
+	}
+	if (fullscreen)								// Are We Still In Fullscreen Mode?
+	{
+		dwExStyle=WS_EX_APPWINDOW;					// Window Extended Style
+		dwStyle=WS_POPUP;						// Windows Style
+		ShowCursor(FALSE);						// Hide Mouse Pointer
+	}
+	else
+	{
+
+		dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;			// Window Extended Style
+		dwStyle=WS_OVERLAPPEDWINDOW;					// Windows Style
+	}
+	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requested Size
+	if (!(hWnd=CreateWindowEx(	dwExStyle,				// Extended Style For The Window
+					"OpenGL",				// Class Name
+					title,					// Window Title
+					WS_CLIPSIBLINGS |			// Required Window Style
+					WS_CLIPCHILDREN |			// Required Window Style
+					dwStyle,				// Selected Window Style
+					0, 0,					// Window Position
+					WindowRect.right-WindowRect.left,	// Calculate Adjusted Window Width
+					WindowRect.bottom-WindowRect.top,	// Calculate Adjusted Window Height
+					NULL,					// No Parent Window
+					NULL,					// No Menu
+					hInstance,				// Instance
+					NULL)))					// Don't Pass Anything To WM_CREATE
+	{
+		KillGLWindow();							// Reset The Display
+		MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
+		return FALSE;							// Return FALSE
+	}
+	
+	pfd.cColorBits = bits;
+	
+	if (!(hDC=GetDC(hWnd)))							// Did We Get A Device Context?
+	{
+		KillGLWindow();							// Reset The Display
+		MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
+		return FALSE;							// Return FALSE
+	}
+	if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))				// Did Windows Find A Matching Pixel Format?
+	{
+		KillGLWindow();							// Reset The Display
+		MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
+		return FALSE;							// Return FALSE
+	}
+	if(!SetPixelFormat(hDC,PixelFormat,&pfd))				// Are We Able To Set The Pixel Format?
+	{
+		KillGLWindow();							// Reset The Display
+		MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
+		return FALSE;							// Return FALSE
+	}
+	if (!(hRC=wglCreateContext(hDC)))					// Are We Able To Get A Rendering Context?
+	{
+		KillGLWindow();							// Reset The Display
+		MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
+		return FALSE;							// Return FALSE
+	}
+	if(!wglMakeCurrent(hDC,hRC))						// Try To Activate The Rendering Context
+	{
+		KillGLWindow();							// Reset The Display
+		MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
+		return FALSE;							// Return FALSE
+	}
+	ShowWindow(hWnd,SW_SHOW);						// Show The Window
+	SetForegroundWindow(hWnd);						// Slightly Higher Priority
+	SetFocus(hWnd);								// Sets Keyboard Focus To The Window
+	ReSizeGLScene(width, height);						// Set Up Our Perspective GL Screen
+	if (!InitGL())								// Initialize Our Newly Created GL Window
+	{
+		KillGLWindow();							// Reset The Display
+		MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
+		return FALSE;							// Return FALSE
+	}
+	return TRUE;								// Success
+}
+
+LRESULT CALLBACK WndProc(	HWND	hWnd,					// Handle For This Window
+				UINT	uMsg,					// Message For This Window
+				WPARAM	wParam,					// Additional Message Information
+				LPARAM	lParam)					// Additional Message Information
+{
+	int i;
+	worker_def * def;
+	FILE * loadfile;
+	char * code;
+	int size;
+	switch (uMsg)								// Check For Windows Messages
+	{
+
+		case WM_ACTIVATE:						// Watch For Window Activate Message
+		{
+			if (!HIWORD(wParam))					// Check Minimization State
+			{
+				active=TRUE;					// Program Is Active
+			}
+			else
+			{
+				active=FALSE;					// Program Is No Longer Active
+			}
+
+			return 0;						// Return To The Message Loop
+		}
+		case WM_SYSCOMMAND:						// Intercept System Commands
+		{
+			switch (wParam)						// Check System Calls
+			{
+				case SC_SCREENSAVE:				// Screensaver Trying To Start?
+				case SC_MONITORPOWER:				// Monitor Trying To Enter Powersave?
+				return 0;					// Prevent From Happening
+			}
+			break;							// Exit
+		}
+		case WM_CLOSE:							// Did We Receive A Close Message?
+		{
+			PostQuitMessage(0);					// Send A Quit Message
+			return 0;						// Jump Back
+		}
+		case WM_KEYDOWN:						// Is A Key Being Held Down?
+		{
+			if(wParam == VK_BACK && buf_size > 0)
+				--buf_size;
+			else if(wParam == VK_F5 && !execute_active)
+			{
+				deflist[current_def].implement_func->num_workers = num_workers;
+				deflist[current_def].implement_func->num_wires = num_wires;
+				fprintf(outfile, "Starting execution.\n");
+				interp_start(-1,FALSE,0,NULL);
+			}
+			else if(wParam == VK_RETURN && buf_size > 0)
+			{
+				text_buf_size = buf_size;
+				memcpy(text_buf, new_name_buf, buf_size);
+				buf_size = 0;
+				if(memcmp(text_buf, "Save:", strlen("Save:")) == 0)
+				{
+					text_buf[text_buf_size]='\0';
+					deflist[current_def].implement_func->num_workers = num_workers;
+					deflist[current_def].implement_func->num_wires = num_wires;
+					save_program(text_buf + strlen("Save:"));
+					text_buf_size = 0;
+				}
+				else if(memcmp(text_buf, "Load:", strlen("Load:")) == 0)
+				{
+					text_buf[text_buf_size]='\0';
+					load_program(text_buf + strlen("Load:"));
+					view_workerlist = deflist[0].implement_func->workerlist;
+					view_wirelist = deflist[0].implement_func->wirelist;
+					num_workers = deflist[0].implement_func->num_workers;
+					num_wires = deflist[0].implement_func->num_wires;
+					text_buf_size = 0;
+				}
+				else if (memcmp(text_buf, "View:", strlen("View:")) == 0)
+				{
+					text_buf[text_buf_size]='\0';
+					deflist[current_def].implement_func->num_workers = num_workers;
+					deflist[current_def].implement_func->num_wires = num_wires;
+					i = find_worker(text_buf+strlen("View:"), NULL, NULL);
+					if(i < 0)
+						current_def = create_worker(text_buf+strlen("View:"), 0, 0, USER_FLAG | WORKER_TYPE) - deflist;
+					else
+						current_def = i;
+					num_workers = deflist[current_def].implement_func->num_workers;
+					num_wires = deflist[current_def].implement_func->num_wires;
+					view_workerlist = deflist[current_def].implement_func->workerlist;
+					view_wirelist = deflist[current_def].implement_func->wirelist;
+					text_buf_size = 0;
+					selected_worker = -1;
+				}
+				else if(memcmp(text_buf, "Import:", strlen("Import:")) == 0)
+				{
+					deflist[current_def].implement_func->num_workers = num_workers;
+					deflist[current_def].implement_func->num_wires = num_wires;
+					text_buf[text_buf_size]='\0';
+					loadfile = fopen(text_buf+strlen("Import:"), "rb");
+					fseek(loadfile, 0, SEEK_END);
+					size = ftell(loadfile);
+					fseek(loadfile, 0, SEEK_SET);
+					code = malloc(size+1);
+					fread(code, 1, size, loadfile);
+					parse(code, size);
+				}
+			}
+			else if(wParam == VK_DELETE)
+			{
+				if(selected_worker != -1)
+				{
+					for(i = 0; i < num_wires; ++i)
+					{
+						if(view_wirelist[i].start_worker == selected_worker || view_wirelist[i].end_worker == selected_worker)
+						{
+							view_wirelist[i] = view_wirelist[num_wires-1];
+							--num_wires;
+							--i;
+						}
+						
+					}
+					view_workerlist[selected_worker] = view_workerlist[num_workers-1];
+					for(i = 0; i < num_wires; ++i)
+					{
+						if(view_wirelist[i].start_worker == num_workers-1)
+							view_wirelist[i].start_worker = selected_worker;
+						if(view_wirelist[i].end_worker == num_workers-1)
+							view_wirelist[i].end_worker = selected_worker;
+					}
+					--num_workers;
+					selected_worker = -1;
+						
+				}
+			}
+
+
+			keys[wParam] = TRUE;					// If So, Mark It As TRUE
+			return 0;						// Jump Back
+		}
+		case WM_KEYUP:							// Has A Key Been Released?
+		{
+			keys[wParam] = FALSE;					// If So, Mark It As FALSE
+			return 0;						// Jump Back
+		}
+		case WM_SIZE:							// Resize The OpenGL Window
+		{
+			ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));		// LoWord=Width, HiWord=Height
+			return 0;						// Jump Back
+		}
+		case WM_RBUTTONDOWN:
+		{
+			view_workerlist[num_workers].xpos = INTX_TO_FLOAT_REL(GET_X_LPARAM(lParam));
+			view_workerlist[num_workers].ypos = INTY_TO_FLOAT_REL(480-GET_Y_LPARAM(lParam));
+			
+			view_workerlist[num_workers].height = 0.25;
+			view_workerlist[num_workers].grabbed=FALSE;
+			if(buf_size > strlen("Data:") && memcmp("Data:", new_name_buf, strlen("Data:")) == 0)
+			{
+				
+				view_workerlist[num_workers].display_type=1;//Rectangle
+				view_workerlist[num_workers].type=0;//Constant
+				view_workerlist[num_workers].num_inputs=0;//Constants don't have inputs
+				view_workerlist[num_workers].num_outputs=1;//Constants have one output
+				view_workerlist[num_workers].null_input = FALSE;
+				memcpy(view_workerlist[num_workers].name, new_name_buf+strlen("Data:"), buf_size-strlen("Data:"));
+				view_workerlist[num_workers].name[buf_size-strlen("Data:")]='\0';
+				view_workerlist[num_workers].width = ((double)(buf_size-strlen("Data:"))+0.5) * INPUT_SIZE;
+				++num_workers;
+				buf_size = 0;
+			}
+			else if(buf_size > strlen("Room:") && memcmp("Room:", new_name_buf, strlen("Room:")) == 0)
+			{
+				view_workerlist[num_workers].type=1;//Room
+				view_workerlist[num_workers].display_type=1;//Rectangle
+				view_workerlist[num_workers].num_inputs=1;
+				view_workerlist[num_workers].num_outputs=1;
+				view_workerlist[num_workers].null_input = FALSE;
+				memcpy(view_workerlist[num_workers].name, new_name_buf+strlen("Room:"), buf_size-strlen("Room:"));
+				view_workerlist[num_workers].name[buf_size-strlen("Room:")]='\0';
+				view_workerlist[num_workers].width = ((double)(buf_size-strlen("Room:"))+0.5) * INPUT_SIZE;
+				++num_workers;
+				buf_size = 0;
+			}
+			else if(buf_size > strlen("Input:") && memcmp("Input:", new_name_buf, strlen("Input:")) == 0)
+			{
+				deflist[current_def].implement_func->num_workers = num_workers;
+				new_name_buf[buf_size] = '\0';
+				MessageBox(NULL, new_name_buf,"Error",MB_OK);
+				add_input(deflist+current_def, new_name_buf + strlen("Input:"), INTX_TO_FLOAT_REL(GET_X_LPARAM(lParam)), INTY_TO_FLOAT_REL(480-GET_Y_LPARAM(lParam)));
+				num_workers = deflist[current_def].implement_func->num_workers;
+			}
+			else if(buf_size > strlen("Output:") && memcmp("Output:", new_name_buf, strlen("Output:")) == 0)
+			{
+				deflist[current_def].implement_func->num_workers = num_workers;
+				new_name_buf[buf_size] = '\0';
+				add_output(deflist+current_def, new_name_buf + strlen("Output:"), INTX_TO_FLOAT_REL(GET_X_LPARAM(lParam)), INTY_TO_FLOAT_REL(480-GET_Y_LPARAM(lParam)));
+				num_workers = deflist[current_def].implement_func->num_workers;
+			}
+			else if(buf_size > strlen("Express:") && memcmp("Express:", new_name_buf, strlen("Express:")) == 0)
+			{
+				deflist[current_def].implement_func->num_workers = num_workers;
+				new_name_buf[buf_size] = '\0';
+				def = create_worker(new_name_buf+strlen("Express:"), 0, 0, USER_FLAG | WORKER_TYPE);
+				parse_body(def, new_name_buf+strlen("Express:"), buf_size-strlen("Express:"));
+				add_worker_to_def(deflist+current_def, def-deflist, INTX_TO_FLOAT_REL(GET_X_LPARAM(lParam)), INTY_TO_FLOAT_REL(480-GET_Y_LPARAM(lParam)));
+				num_workers = deflist[current_def].implement_func->num_workers;
+				buf_size = 0;
+			}
+			else
+			{
+				memcpy(view_workerlist[num_workers].name, new_name_buf, buf_size);
+				view_workerlist[num_workers].name[buf_size] = '\0';
+				for(i = 0; i < num_defs; ++i)
+				{
+					fprintf(outfile, "Comparing %s with %s(%d)\n", view_workerlist[num_workers].name, deflist[i].name, i);
+					if(strcmp(view_workerlist[num_workers].name, deflist[i].name)==0)
+					{
+						view_workerlist[num_workers].display_type=2;//Trapezoid
+						view_workerlist[num_workers].type=2;//Worker
+						view_workerlist[num_workers].num_inputs=deflist[i].num_inputs;
+						view_workerlist[num_workers].num_outputs=deflist[i].num_outputs;
+						view_workerlist[num_workers].null_input = FALSE;
+						view_workerlist[num_workers].value_index = i;
+						view_workerlist[num_workers].width = ((double)buf_size+0.5) * INPUT_SIZE;
+						
+						++num_workers;
+						buf_size = 0;
+						break;
+					}
+				}
+				if(i >= num_defs)
+				{
+					strcpy(new_name_buf, "I don't know a worker with that name.");
+					buf_size = strlen(new_name_buf);
+				}
+			}
+			if(view_workerlist[num_workers-1].width <= (double)view_workerlist[num_workers-1].num_outputs * OUTPUT_SIZE)
+				view_workerlist[num_workers-1].width = (double)view_workerlist[num_workers-1].num_outputs * (OUTPUT_SIZE*1.1);
+			if(view_workerlist[num_workers-1].width <= (double)view_workerlist[num_workers-1].num_inputs * INPUT_SIZE)
+				view_workerlist[num_workers-1].width = (double)view_workerlist[num_workers-1].num_inputs * (INPUT_SIZE*1.1);
+			
+			
+			break;
+		}
+
+		case WM_LBUTTONDOWN:
+		{
+			mouse_leftstart_down=mouse_left_down=TRUE;
+			mouse_lastx = mouse_curx = GET_X_LPARAM(lParam);
+			mouse_lasty = mouse_cury = 480-GET_Y_LPARAM(lParam);
+			checked_mouse_pos=FALSE;
+			return 0;
+		}
+		case WM_LBUTTONUP:
+		{
+			mouse_leftstart_down=mouse_left_down=FALSE;
+			return 0;
+		}
+		case WM_MOUSEMOVE:
+		{
+			//If no one has checked the mouse position vars, this could cause bugs
+			if(checked_mouse_pos)
+			{
+				mouse_lastx = mouse_curx;
+				mouse_lasty = mouse_cury;
+			}
+			mouse_curx = GET_X_LPARAM(lParam);
+			mouse_cury = 480-GET_Y_LPARAM(lParam);
+			checked_mouse_pos=FALSE;
+			return 0;
+		}
+		case WM_CHAR:
+		{
+			if(wParam >= 0x20)
+			{
+				new_name_buf[buf_size++]=wParam&0xFF;
+			}
+			return 0;
+		}
+			
+	}
+	// Pass All Unhandled Messages To DefWindowProc
+	return DefWindowProc(hWnd,uMsg,wParam,lParam);
+}
+
+VOID CALLBACK DoFrame(HWND myhWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+	if(active)
+	{
+		DrawGLScene();				// Draw The Scene
+		SwapBuffers(hDC);			// Swap Buffers (Double Buffering)
+	}
+}
+
+int WINAPI WinMain(	HINSTANCE	hInstance,				// Instance
+			HINSTANCE	hPrevInstance,				// Previous Instance
+			LPSTR		lpCmdLine,				// Command Line Parameters
+			int		nCmdShow)				// Window Show State
+{
+	MSG	msg;								// Windows Message Structure
+	BOOL	done=FALSE;							// Bool Variable To Exit Loop
+	// Ask The User Which Screen Mode They Prefer
+	if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
+	{
+		fullscreen=FALSE;						// Windowed Mode
+	}
+	// Create Our OpenGL Window
+	if (!CreateGLWindow("Visuality",640,480,16,fullscreen))
+	{
+		return 0;							// Quit If Window Was Not Created
+	}
+
+	initworkers();
+	view_workerlist = deflist[0].implement_func->workerlist;
+	view_wirelist = deflist[0].implement_func->wirelist;
+	
+	
+	outfile = fopen("output.txt", "w");
+	
+	SetTimer(hWnd, 1, 17, DoFrame);
+
+	
+	while(!done)								// Loop That Runs Until done=TRUE
+	{
+		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))			// Is There A Message Waiting?
+		{
+			if (msg.message==WM_QUIT)				// Have We Received A Quit Message?
+			{
+				done=TRUE;					// If So done=TRUE
+			}
+			else							// If Not, Deal With Window Messages
+			{
+				TranslateMessage(&msg);				// Translate The Message
+				DispatchMessage(&msg);				// Dispatch The Message
+			}
+		}
+		// Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()
+		if (active)						// Program Active?
+		{
+			if (keys[VK_ESCAPE])				// Was ESC Pressed?
+			{
+				done=TRUE;				// ESC Signalled A Quit
+			}
+			else						// Not Time To Quit, Update Screen
+			{
+
+				
+			}
+			
+			if (keys[VK_F1])					// Is F1 Being Pressed?
+			{
+				keys[VK_F1]=FALSE;				// If So Make Key FALSE
+				KillTimer(hWnd, 1);
+				KillGLWindow();					// Kill Our Current Window
+				fullscreen=!fullscreen;				// Toggle Fullscreen / Windowed Mode
+				// Recreate Our OpenGL Window
+				if (!CreateGLWindow("Rini's Love Quest",640,480,16,fullscreen))
+				{
+					return 0;				// Quit If Window Was Not Created
+				}
+				SetTimer(hWnd, 1, 17, DoFrame);
+			}
+		}
+		Sleep(0);
+	}
+	KillTimer(hWnd, 1);
+
+	// Shutdown
+	KillGLWindow();								// Kill The Window
+	return (msg.wParam);							// Exit The Program
+}