/**************************************************************************/
/* The next few lines are standard "boiler plate" code all UDF's have     */
/**************************************************************************/

#include <windows.h>
#include <dde.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>

typedef struct
	{
   double x, y, z, l, m, n, opd, intensity;
	double Exr, Exi, Eyr, Eyi, Ezr, Ezi;
	int wave, error, vigcode, want_opd;
	}DDERAYDATA;

/* boiler plate declarations for functions in zclient we will call */
void WaitForData(HWND hwnd);
char *GetString(char *szBuffer, int n, char *szSubString);
void remove_quotes(char *s);
int PostRequestMessage(char *szItem, char *szDataOut);
int PostArrayTraceMessage(char *szBuffer, DDERAYDATA *RD);
void CenterWindow(HWND hwnd);
void UserFunction(char *szCommandLine);
void MakeEmptyWindow(int text, char *szAppName, char *szOptions);
void Get_2_5_10(double cmax, double *cscale);

/* boiler plate global variables used by the client code */
extern HINSTANCE globalhInstance;
extern HWND hwndClient;


/**************************************************/
/* Below is the code specific to this UDF program */
/**************************************************/

// Program written by James Sutter Sept 1997
// Version 2.0

// Version 2.1 modified by Kenneth Moore October 2003 to fix multicon WAVE bug

// Version 2.2 modified by Kenneth Moore January 2005 to fix long string bug by using SetSettingsData item


/* declare the dialog box function for the settings box */
LRESULT CALLBACK SurDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);

/* other global variables */
int imagesurf, numsurfs, numfields;
double min_wave, max_wave, min_trans, max_trans, ex, ey, x_phase, y_phase;
int nUnpolarized;
int field, sampling, steps;
#define MAX_POINTS 1000
#define MAX_SELECTIONS 20

/* okay, now the actual code that creates the UDF data for display in a ZEMAX window */
/* this function MUST be called UserFunction and take the command line argument      */

void UserFunction(char *szCommandLine)
{

/* local variables  */
FILE *output;
char szModuleName[260], szOutputFile[260];
static char szAppName[] = "Transmission vs. Wavelength Plot";	/* Window title */
static char szBuffer[5000], szSub[256], lensname[100], lensfile[256], plotdate[100];
int  text, show_settings, button;
int  i, j;
int unitcode;
int numwave, numrays, fieldtype;
double tx,ty,ta,tw,th,tc, aspect; /* graphics window text coordinates */
char graphtext[100];
double stepsize, h;
double sys_min_wave, sys_max_wave, wave, wave_1, waveweight;
double xfield, yfield, maxfield;
double fTD[2][MAX_POINTS + 1];
double px, py, hx, hy, dp;
int nPTC;

DDERAYDATA PolRaydata[43 * 43 + 1]; // structure size based on max sampling
DDERAYDATA RegRaydata[43 * 43 + 1]; // structure size based on max sampling

/* extract the command line arguments */
text          = atoi(GetString(szCommandLine, 0, szSub));
show_settings = atoi(GetString(szCommandLine, 1, szSub));
GetString(szCommandLine, 2, szOutputFile);
remove_quotes(szOutputFile);

/* first, update the lens so we have the latest data; and then test to make sure the system is valid */
PostRequestMessage("GetUpdate", szBuffer);

if (atoi(GetString(szBuffer, 0, szSub)))
	{
   /* the current lens cannot be traced! */
   /* some features may be able to create data without tracing rays; some can't */
   /* If data cannot be created return "empty" data displays */
   sprintf(szBuffer,"%i", imagesurf);
   MakeEmptyWindow(text, szAppName, szBuffer);
   return;
   }

/*

Modified 10-21-2003 Kenneth Moore
If this is a multi-config lens which includes WAVE operands, the method will fail.
Disable all WAVE operands by changing them to OFF operands.

*/

if (1)
	{
	int nummc;

	PostRequestMessage("GetMulticon, 1, 1", szBuffer);
	nummc = atoi(GetString(szBuffer, 2, szSub));

	for (i = 1; i <= nummc; i++)
		{
		/* is this mc operand a WAVE? */
		sprintf(szBuffer, "GetMulticon, 0, %i", i);
		PostRequestMessage(szBuffer, szBuffer);
		if (0 == strcmp("WAVE", GetString(szBuffer, 0, szSub)))
			{
			/* yes, it is! Disable it by making it OFF */
			sprintf(szBuffer, "SetMulticon, 0, %i, MOFF, 0, 0, 0", i);
			PostRequestMessage(szBuffer, szBuffer);
			}
		}
	}

/* END of modifications */

/* now get the file */
PostRequestMessage("GetFile", lensfile);
lensfile[strlen(lensfile)-2] = '\0';

/* now get the lens name */
PostRequestMessage("GetName", lensname);
lensname[strlen(lensname)-2] = '\0';

/* now get the date */
PostRequestMessage("GetDate", plotdate);
plotdate[strlen(plotdate)-2] = '\0';

/* now get the system data; we need the number of surfaces and lens units*/
PostRequestMessage("GetSystem", szBuffer);
imagesurf = atoi(GetString(szBuffer, 0, szSub));
unitcode = atoi(GetString(szBuffer, 1, szSub));

/* now get the number of field points*/
PostRequestMessage("GetField, 0", szBuffer);
numfields = atoi(GetString(szBuffer,1, szSub));
/* get the field type */
fieldtype = atoi(GetString(szBuffer,0, szSub));

/* find maximum field to use for normalized field coordinates */
sprintf(szBuffer, "GetField, 1");
PostRequestMessage(szBuffer, szBuffer);
xfield = atof(GetString(szBuffer,0,szSub));
yfield = atof(GetString(szBuffer,1,szSub));
maxfield = sqrt(xfield * xfield + yfield * yfield);
for (i = 1; i<=numfields; i++)
   {
	sprintf(szBuffer, "GetField, %i", i);
	PostRequestMessage(szBuffer, szBuffer);
	xfield = atof(GetString(szBuffer,0,szSub));
	yfield = atof(GetString(szBuffer,1,szSub));
	xfield = sqrt(xfield * xfield + yfield * yfield);
   if (xfield > maxfield) maxfield = xfield;
   }

/* get the number of wavelengths */
PostRequestMessage("GetWave, 0", szBuffer);
numwave = atoi(GetString(szBuffer, 1, szSub));

/* get the wavelengths and find min and max */
PostRequestMessage("GetWave, 1", szBuffer);
wave_1 = atof(GetString(szBuffer,0,szSub));
waveweight = atof(GetString(szBuffer,1,szSub));
/* save wavelength 1 in a temp variable to restore at end */
min_wave = wave_1;
max_wave = min_wave;
for (i = 1; i<=numwave; i++)
   {
	sprintf(szBuffer, "GetWave, %i", i);
  	PostRequestMessage(szBuffer, szBuffer);
	wave = atof(GetString(szBuffer,0,szSub));
   if (wave < min_wave) min_wave = wave;
   if (wave > max_wave) max_wave = wave;
   }
sys_min_wave = min_wave;
sys_max_wave = max_wave;

/* get the plot's aspect ratio */
PostRequestMessage("GetAspect", szBuffer);
aspect = atof(GetString(szBuffer, 0, szSub));

/* Get settings */

// this is done by passing the current output file name back to ZEMAX so ZEMAX knows which window this is for
sprintf(szBuffer, "GetSettingsData,\"%s\",0", szOutputFile);
PostRequestMessage(szBuffer, szBuffer);

// strip off the last 2 bytes of junk
if (strlen(szBuffer) > 1) szBuffer[strlen(szBuffer) - 2] = '\0';

// debug tool
//sprintf(szSub,"*%s*", szBuffer);
//MessageBox(hwndClient, szSub, "Settings:", MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);

if (szBuffer[0])
	{
	// min_wave, max_wave, ex, ey, x_phase, y_phase, min_trans, max_trans, field, sampling, steps, nUnpolarized

	/* get the wavelength settings */
	min_wave = atof(GetString(szBuffer, 0, szSub));
	max_wave = atof(GetString(szBuffer, 1, szSub));

	/* get the polarization settings*/
	ex = atof(GetString(szBuffer, 2, szSub));
	ey = atof(GetString(szBuffer, 3, szSub));
   x_phase = atof(GetString(szBuffer, 4, szSub));
   y_phase = atof(GetString(szBuffer, 5, szSub));
   nUnpolarized = atoi(GetString(szBuffer, 11, szSub));

	/* get transmission plot range */
	min_trans = atof(GetString(szBuffer, 6, szSub));
	max_trans = atof(GetString(szBuffer, 7, szSub));

	/* get the field, sampling, and steps */
	field = atoi(GetString(szBuffer, 8, szSub));
   sampling = atoi(GetString(szBuffer, 9, szSub));
	steps = atoi(GetString(szBuffer, 10, szSub));
   }
else
	{
   /* Set reasonable defaults if no settings were passed */
	/* Use the system settings for polarization state */
	PostRequestMessage("GetPolState", szBuffer);
	nUnpolarized = atoi(GetString(szBuffer,0,szSub));
   ex = atof(GetString(szBuffer,1,szSub));
	ey = atof(GetString(szBuffer,2,szSub));
   x_phase = atof(GetString(szBuffer,3,szSub));
   y_phase = atof(GetString(szBuffer,4,szSub));
	min_trans = 0;
	max_trans = 1;
	field = 1;
   sampling = 5;
   steps = 5;
	}

check_again:;
/* make sure settings entered by the user are valid */
if (min_wave < sys_min_wave) min_wave = sys_min_wave;
if (min_wave > sys_max_wave) min_wave = sys_max_wave;
if (max_wave > sys_max_wave) max_wave = sys_max_wave;
if (max_wave < sys_min_wave) max_wave = sys_min_wave;
if (max_wave < min_wave) max_wave = min_wave;
if (min_trans < 0 || min_trans >= 1) min_trans = 0;
if (max_trans <= 0 || max_trans > 1) max_trans = 1;
if (max_trans < min_trans) max_trans = min_trans;
if (steps > MAX_POINTS) steps = MAX_POINTS;
if (steps <= 0) steps = 1;

/* is the user requesting to see the settings box? */
if (show_settings)
	{
   /* we need to display the settings box! */
   button = DialogBox(globalhInstance, "SurDlg", hwndClient, (DLGPROC) SurDlgProc);
	if (button == IDCANCEL)
   	{
		sprintf(szBuffer,"ReleaseWindow,%s", szOutputFile);
		PostRequestMessage(szBuffer, szBuffer);
      return;
      }

	/* check it one more time! */
   show_settings = 0;
   goto check_again;
   }

/* get the x, y field angles for the given field number */
sprintf(szBuffer, "GetField, %i", field);
PostRequestMessage(szBuffer, szBuffer);
xfield = atof(GetString(szBuffer,0,szSub));
yfield = atof(GetString(szBuffer,1,szSub));

/* determine normalized field coordinates */
if (maxfield > 0)
	{
	hx = xfield/maxfield;
	hy = yfield/maxfield;
   }
else
	{
   hx = 0;
   hy = 0;
   }

/* finally, we have all the settings. Trace rays and store data. */

/* calculate wavelength stepsize*/
stepsize = (max_wave - min_wave) / steps;
wave = min_wave - stepsize;

for (i = 0; i <= steps; i++)
	{
	/* increment wavelength(1) by stepsize */
   wave = wave + stepsize;
	/* store the wavelength in the transmission data array */
   fTD[0][i] = wave;
   sprintf(szBuffer,"SetWave, 1, %f, 1\n", wave);
   PostRequestMessage(szBuffer, szBuffer);
	/* call GetUpdate to recompute the index after changing any of the system parameters */
   sprintf(szBuffer,"GetUpdate\n", wave);
   PostRequestMessage(szBuffer, szBuffer);

	/* calculate normalized pupil coordinates - grid pattern */
	nPTC = 0;
	dp = 2/ (double) sampling;
	for (py = -1; py <= 1; py = py + dp)
   	{
		for (px = -1; px <= 1; px = px + dp)
			{
		   if ((px*px + py*py) <= 1)
	      	{
	         nPTC = nPTC + 1; /* increment counter for rays in pupil */

	  	      /* initialize pol trace array elements */
				PolRaydata[nPTC].x = hx;	/* x field */
				PolRaydata[nPTC].y = hy;	/* y field */
		  	 	PolRaydata[nPTC].z = px; /* x pupil */
				PolRaydata[nPTC].l = py; /* y pupil */
				PolRaydata[nPTC].intensity = 1; /* start at 1*/
				PolRaydata[nPTC].Exr = 0.0;   /* ignored if zero */				
				PolRaydata[nPTC].Exi = 0.0;   /* ignored if zero */				
				PolRaydata[nPTC].Eyr = 0.0;   /* ignored if zero */				
				PolRaydata[nPTC].Eyi = 0.0;   /* ignored if zero */				
				PolRaydata[nPTC].Ezr = 0.0;   /* ignored if zero */				
				PolRaydata[nPTC].Ezi = 0.0;   /* ignored if zero */				
				PolRaydata[nPTC].wave = 1;    /* wavelength */
				PolRaydata[nPTC].error = 0;   /* initially zero */
				PolRaydata[nPTC].vigcode = 0; /* initially zero */
				PolRaydata[nPTC].want_opd = 0; /* ignored zero */

				/* initialize get trace array elements */
				RegRaydata[nPTC].x = hx; /* x field */
				RegRaydata[nPTC].y = hy; /* y field */
		  	 	RegRaydata[nPTC].z = px; /* x pupil */
				RegRaydata[nPTC].l = py; /* y pupil */
				RegRaydata[nPTC].wave = 1; /* wavelength */
				RegRaydata[nPTC].error = 0; /* initially zero */
				RegRaydata[nPTC].vigcode = 0; /* initially zero */
				RegRaydata[nPTC].want_opd = 0; /* OPD not needed */
	         }
			}
  		}

	/* initialize pol trace array structure (element zero) */
   /* pre-normalize ex, and ey by electric field vector */
   h = sqrt(ex*ex + ey*ey);
	PolRaydata[0].x = ex/h;  		/* E field amp in x */
	PolRaydata[0].y = ey/h;  		/* E field amp in y */
	PolRaydata[0].z = x_phase;  /* Phase in deg for Ex */
	PolRaydata[0].l = y_phase;  /* Phase in deg for Ey */
	if (nUnpolarized == 1)
		{
		PolRaydata[0].x = 0;  /* E field amp in x */
		PolRaydata[0].y = 0;  /* E field amp in y */
  		PolRaydata[0].z = 0;  /* Phase in deg for Ex */
		PolRaydata[0].l = 0;  /* Phase in deg for Ey */
		}
	PolRaydata[0].opd = 2; /* mode 2 for polarization ray trace*/
	PolRaydata[0].intensity = 0.0; /* ignored */	
	PolRaydata[0].Exr = 0.0;   /* ignored */				
	PolRaydata[0].Exi = 0.0;   /* ignored */				
	PolRaydata[0].Eyr = 0.0;   /* ignored */				
	PolRaydata[0].Eyi = 0.0;   /* ignored */				
	PolRaydata[0].Ezr = 0.0;   /* ignored */				
	PolRaydata[0].Ezi = 0.0;   /* ignored */				
	PolRaydata[0].wave = 0; /* real rays */
	PolRaydata[0].error = nPTC;  /* number of rays in array */
	PolRaydata[0].vigcode = 0;  /* initially zero */
	PolRaydata[0].want_opd = -1; /* -1 for image surface */

	/* initialize get trace array structure (element zero) */
	RegRaydata[0].opd = 0; /* mode 0 for get ray trace*/
	RegRaydata[0].wave = 0;  /* real rays */
	RegRaydata[0].error = nPTC;  /* number of rays in array */
	RegRaydata[0].vigcode = 0;   /* initially zero */
	RegRaydata[0].want_opd = -1; /* -1 for image surface */


	/* Now go get the data */
	PostArrayTraceMessage(szBuffer, PolRaydata);
	PostArrayTraceMessage(szBuffer, RegRaydata);
	/* Okay, we got the data! There, wasn't that easy! */

   /* Test each array element for ray errors and vigetting */
   /* add intensities */
	fTD[1][i] = 0;
	numrays = 0;
   for (j = 1; j <= nPTC; j++)
   	{
      if (RegRaydata[j].error == 0 && RegRaydata[j].vigcode == 0)
      	{
         /* if no errors, add intensity data */
         fTD[1][i] = fTD[1][i] + PolRaydata[j].intensity;
         numrays++;
			}
		}
   /* compute average intensity */
	//if(numrays > 0) fTD[1][i] = fTD[1][i]/numrays;
	if(nPTC > 0) fTD[1][i] = fTD[1][i]/nPTC;
   }

/* restore first wavelength and weight*/
sprintf(szBuffer,"SetWave, 1, %f, %f\n", wave_1, waveweight);
PostRequestMessage(szBuffer, szBuffer);

/* open a file for output */
if ((output = fopen(szOutputFile, "wt")) == NULL)
	{
   /* can't open the file!! */
	MessageBox(hwndClient, szOutputFile, "Output file:", MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);
   return;
   }

/* this windows function gives us the name of our own executable; we pass this back to ZEMAX */
GetModuleFileName(globalhInstance, szModuleName, 255);

/* ok, do you want a text listing or a plot? */
if (text)
	{
   fputs("Listing of Transmission vs. Wavelength Data\n\n",output);
   sprintf(szBuffer, "File : %s\n", lensfile);
   fputs(szBuffer,output);
   sprintf(szBuffer, "Title: %s\n", lensname);
   fputs(szBuffer,output);
   sprintf(szBuffer, "Date : %s\n\n", plotdate);
   fputs(szBuffer,output);

   sprintf(szBuffer, "Field Pos: %.2f, %.2f ", xfield, yfield);
   if (fieldtype == 0) strcat(szBuffer, "deg\n");
   if (fieldtype == 1 || fieldtype == 2)
     	{
		if (unitcode == 0) strcat(szBuffer, "mm\n");
		if (unitcode == 1) strcat(szBuffer, "cm\n");
      if (unitcode == 2) strcat(szBuffer, "in\n");
      if (unitcode == 3) strcat(szBuffer, "M\n");
      }
   fputs(szBuffer,output);

  	sprintf(szBuffer, "\nInput Polarization\n");
   fputs(szBuffer,output);

	if (nUnpolarized)
   	{
     	sprintf(szBuffer, " Field is upolarized\n");
      fputs(szBuffer,output);
      }
   else
   	{
		sprintf(szBuffer, " X-Field : %8.4f\n", ex);
      fputs(szBuffer,output);
		sprintf(szBuffer, " Y-Field : %8.4f\n", ey);
      fputs(szBuffer,output);
		sprintf(szBuffer, " X-Phase : %8.2f deg\n", x_phase);
      fputs(szBuffer,output);
		sprintf(szBuffer, " Y-Phase : %8.2f deg\n", y_phase);
      fputs(szBuffer,output);
		}

	sprintf(szBuffer, "\nGrid Size: %i x %i\n", sampling, sampling);
   fputs(szBuffer,output);


   fputs("\n   Wavelength     Transmission\n",output);

   for (i = 0; i <= steps; i++)
   	{
      sprintf(szBuffer,"%12.4f  %12.6f\n", fTD[0][i], fTD[1][i]);
      fputs(szBuffer,output);
      }

	/* close the file! */
   fclose(output);
   
   /* store the settings we used */
	sprintf(szBuffer,"SetSettingsData,0,%.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %i %i %i %i", min_wave, max_wave, ex, ey, x_phase, y_phase, min_trans, max_trans, field, sampling, steps, nUnpolarized);
   PostRequestMessage(szBuffer, szBuffer);

	/* create a text window. Note we pass back the filename, module, and application title name */
   sprintf(szBuffer,"MakeTextWindow,\"%s\",\"%s\",\"%s\"", szOutputFile, szModuleName, szAppName);
   PostRequestMessage(szBuffer, szBuffer);
   }
else
	{
   /* okay, make a plot instead */

   double oldx, oldy, x, y, left, right, top, bottom, xtick, ytick, txwidth;

   /* make a standard ZEMAX frame */
   /* note the first graphic command must be FRAME or NOFRAME */
   fputs("FRAME\n",output);

   /* draw the main data box */
   left = .2;
   right = .9;
   bottom = .3;
   top = .9;
   xtick = .010;
   ytick = .015;
   txwidth = 1.0/70.0;
	/* txeheight would be 1.0/40.0 */

   sprintf(szBuffer,"BOX %.4f %.4f %.4f %.4f\n", left, bottom, right, top);
   fputs(szBuffer,output);

   /* give it a plot title */
   fputs("TITLE \"Transmission vs. Wavelength\"\n",output);

   /* Put the lens name, etc.. on it in the usual place */
   fputs("ADDRESS\n",output);
   fputs("LENSNAME\n",output);
   fputs("DATE\n",output);

   sprintf(szBuffer,"DATA 2 \"Field Pos: %.4f, %.4f ", xfield, yfield);
   if (fieldtype == 0) strcat(szBuffer, "deg\"\n");
   if (fieldtype == 1 || fieldtype == 2)
     	{
		if (unitcode == 0) strcat(szBuffer, "mm\"\n");
		if (unitcode == 1) strcat(szBuffer, "cm\"\n");
      if (unitcode == 2) strcat(szBuffer, "in\"\n");
      if (unitcode == 3) strcat(szBuffer, "M\"\n");
      }
	fputs(szBuffer,output);
   	if (nUnpolarized)
   	{
	  	sprintf(szBuffer,"DATA 3 \"Field is unpolarized.\"\n");
      fputs(szBuffer,output);
      }
   else
   	{
	  	sprintf(szBuffer,"DATA 3 \"Ex:%6.3f Ey:%6.3f Px:%6.3f Py:%6.3f\"\n", ex, ey, x_phase, y_phase);
      fputs(szBuffer,output);
      }

   /* okay, make tick marks */
   for (i = 0; i <= 10; i++)
   	{
      /* vertical tic marks*/
      y = bottom + (top - bottom)* (float) i / 10.0;
      sprintf(szBuffer,"LINE %.4f %.4f %.4f %.4f\n", left, y, left+xtick, y);
      fputs(szBuffer,output);
      sprintf(szBuffer,"LINE %.4f %.4f %.4f %.4f\n", right, y, right-xtick, y);
      fputs(szBuffer,output);

      /* horizontal tic marks*/
      x = left + (right - left)* (float) i / 10.0;
      sprintf(szBuffer,"LINE %.4f %.4f %.4f %.4f\n", x, bottom, x, bottom+ytick);
      fputs(szBuffer,output);
      sprintf(szBuffer,"LINE %.4f %.4f %.4f %.4f\n", x, top, x, top-ytick);
      fputs(szBuffer,output);


      if (i == 0 || i == 5 || i == 10)
      	{
         /* label the tic marks */

         /* vertical */
         sprintf(szBuffer,"TEXT \"%.3f\" %.4f %.4f\n", min_trans + (float) i / 10.0 * (max_trans - min_trans), .11, y);
         fputs(szBuffer,output);

			/* horizontal */
			if (i == 0)
         	{
	         /* if 0 - align number with left side of plot */
	         sprintf(szBuffer,"TEXT \"%.5f\" %.4f %.4f\n", min_wave + (float) i  / 10.0 * (max_wave - min_wave), x, bottom-.025);
	         fputs(szBuffer,output);
            }
			if (i == 5)
         	{
	         /* if 5 - align number under middle tick mark */
				sprintf(graphtext, "%.5f", min_wave + (float) i  / 10.0 * (max_wave - min_wave));
 				x = x - txwidth * (((float) strlen(graphtext)) /2.0 - .5 );
	         sprintf(szBuffer,"TEXT \"%s\" %.4f %.4f\n", graphtext, x, bottom-.025);
	         fputs(szBuffer,output);
            }
			if (i == 10)
         	{
	         /* if 10 - align number with right side of plot  */
				sprintf(graphtext, "%.5f", min_wave + (float) i  / 10.0 * (max_wave - min_wave));
 				x = x - txwidth * ((float) strlen(graphtext) - .5);
	         sprintf(szBuffer,"TEXT \"%s\" %.4f %.4f\n", graphtext, x, bottom-.025);
	         fputs(szBuffer,output);
            }
         }
      }

	/* add vertical axis label */
	sprintf(graphtext, "Transmission");
	tc = (top+bottom)/2.0;
   ta = 90;
   tw = 10.0;
   th = 10.0;
   tx = left*.3;
   ty = tc - (tw/10.0 * txwidth / aspect * ((float) strlen(graphtext)/2.0 -.5));
   sprintf(szBuffer,"TEXT \"%s\" %.4f %.4f %.4f %.4f %.4f\n", graphtext, tx, ty, ta, tw, th);
   fputs(szBuffer,output);

   /* add horizontal axis label */
	sprintf(graphtext, "Wavelength in µm");
	tc = (left+right)/2.0;
   ta = 0;
   tw = 10.0;
   th = 10.0;
   tx = tc - (tw/10.0 * txwidth * ((float) strlen(graphtext)/2.0 -.5));
   ty = .2 + .3*(bottom - .2); /* align between graph and text frame */
   sprintf(szBuffer,"TEXT \"%s\" %.4f %.4f %.4f %.4f %.4f\n", graphtext, tx, ty, ta, tw, th);
   fputs(szBuffer,output);

   /* Ok, plot the data in color */
   fputs("COLOR 1\n",output);

	oldx = 0.0;
   oldy = 0.0;
   for (i = 0; i <= steps; i++)
   	{
      x = left + (right-left)* (double) i / (double) steps;
      y = bottom + (top-bottom) * (fTD[1][i] - min_trans) / (max_trans - min_trans);
		/* join points within the plot box */
      if (i > 0)
      	{
			if ( y >= bottom && y <= top && oldy >= bottom && oldy <= top)
				{
	         sprintf(szBuffer,"LINE %.4f %.4f %.4f %.4f\n", oldx, oldy, x, y);
	         fputs(szBuffer,output);
            }
         }
      oldx = x;
      oldy = y;
      }

   fclose(output);

   /* store the settings we used */
	sprintf(szBuffer,"SetSettingsData,0,%.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %i %i %i %i", min_wave, max_wave, ex, ey, x_phase, y_phase, min_trans, max_trans, field, sampling, steps, nUnpolarized);
   PostRequestMessage(szBuffer, szBuffer);

   /* note the text flag is 1, because we can do text! */
   sprintf(szBuffer,"MakeGraphicWindow,\"%s\",\"%s\",\"%s\",1", szOutputFile, szModuleName, szAppName);
   PostRequestMessage(szBuffer, szBuffer);
   }

}


LRESULT CALLBACK SurDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
	{
	char szDisplay[300];
	HWND hwndCntl;
	int i;
	WORD wID;

	wID = LOWORD(wParam);
	switch(message)
		{
		case WM_INITDIALOG:
			CenterWindow(hDlg);
			SetWindowText(hDlg, "Transmission vs. Wavelength Settings");

         /* initialize editbox with min wave*/
  			hwndCntl = GetDlgItem(hDlg, 1000);
         sprintf(szDisplay, "%.5f", min_wave);
         SetWindowText(hwndCntl, szDisplay);

         /* initialize editbox with max wave*/
  			hwndCntl = GetDlgItem(hDlg, 1001);
         sprintf(szDisplay, "%.5f", max_wave);
         SetWindowText(hwndCntl, szDisplay);

         /* initialize editbox with X e-field*/
  			hwndCntl = GetDlgItem(hDlg, 1002);
         sprintf(szDisplay, "%.4f", ex);
         SetWindowText(hwndCntl, szDisplay);

         /* initialize editbox with Y e-field*/
  			hwndCntl = GetDlgItem(hDlg, 1003);
         sprintf(szDisplay, "%.4f", ey);
         SetWindowText(hwndCntl, szDisplay);

         /* initialize editbox with X-phase*/
  			hwndCntl = GetDlgItem(hDlg, 1004);
         sprintf(szDisplay, "%.4f", x_phase);
         SetWindowText(hwndCntl, szDisplay);

         /* initialize editbox with Y-phase*/
  			hwndCntl = GetDlgItem(hDlg, 1005);
         sprintf(szDisplay, "%.4f", y_phase);
         SetWindowText(hwndCntl, szDisplay);

         /* initialize editbox with min trans*/
  			hwndCntl = GetDlgItem(hDlg, 1006);
         sprintf(szDisplay, "%.4f", min_trans);
         SetWindowText(hwndCntl, szDisplay);

         /* initialize editbox with max trans*/
  			hwndCntl = GetDlgItem(hDlg, 1007);
         sprintf(szDisplay, "%.4f", max_trans);
         SetWindowText(hwndCntl, szDisplay);

			/* fill the combo box dialog with fields*/
			hwndCntl = GetDlgItem(hDlg, 1008);
			for (i=0; i < numfields; i++)
				{
				sprintf(szDisplay,"%i",i+1);
				SendMessage(hwndCntl, CB_ADDSTRING, i, (LONG) (LPSTR) szDisplay);
				}
			SendMessage(hwndCntl, CB_SETCURSEL, field -1, 0L);

			/* fill the combo box dialog with sampling options*/
			hwndCntl = GetDlgItem(hDlg, 1009);
			for (i=0; i <= MAX_SELECTIONS; i++)
				{
				sprintf(szDisplay,"%i x %i",3+2*i, 3+2*i);
				SendMessage(hwndCntl, CB_ADDSTRING, i, (LONG) (LPSTR) szDisplay);
				}
			SendMessage(hwndCntl, CB_SETCURSEL, (sampling - 3)/2, 0L);

         /* initialize editbox with number of steps*/
  			hwndCntl = GetDlgItem(hDlg, 1010);
         sprintf(szDisplay, "%i", steps);
         SetWindowText(hwndCntl, szDisplay);

         /* initialize unpolarized checkbox */
  			hwndCntl = GetDlgItem(hDlg, 1011);
  			SendMessage(hwndCntl, BM_SETCHECK, nUnpolarized, 0L);

			return TRUE;

		case WM_COMMAND:
			switch(wID)
				{
				case IDOK:

					/* get min wave */
					hwndCntl = GetDlgItem(hDlg, 1000);
               GetWindowText(hwndCntl, szDisplay, 24);
					min_wave = atof(szDisplay);

               /* get max wave */
					hwndCntl = GetDlgItem(hDlg, 1001);
               GetWindowText(hwndCntl, szDisplay, 24);
					max_wave = atof(szDisplay);

               /* get ex */
					hwndCntl = GetDlgItem(hDlg, 1002);
               GetWindowText(hwndCntl, szDisplay, 24);
					ex = atof(szDisplay);

               /* get ey */
					hwndCntl = GetDlgItem(hDlg, 1003);
               GetWindowText(hwndCntl, szDisplay, 24);
					ey = atof(szDisplay);

               /* get x-phase */
					hwndCntl = GetDlgItem(hDlg, 1004);
               GetWindowText(hwndCntl, szDisplay, 24);
					x_phase = atof(szDisplay);

               /* get y-phase */
					hwndCntl = GetDlgItem(hDlg, 1005);
               GetWindowText(hwndCntl, szDisplay, 24);
					y_phase = atof(szDisplay);

               /* get min trans */
					hwndCntl = GetDlgItem(hDlg, 1006);
               GetWindowText(hwndCntl, szDisplay, 24);
					min_trans = atof(szDisplay);
               if (min_trans < 0 || min_trans > 1) min_trans = 0;

               /* get max trans */
					hwndCntl = GetDlgItem(hDlg, 1007);
               GetWindowText(hwndCntl, szDisplay, 24);
					max_trans = atof(szDisplay);

					/* get field */
					hwndCntl = GetDlgItem(hDlg, 1008);
					field = (WORD) SendMessage(hwndCntl, CB_GETCURSEL, 0, 0L) + 1;

					/* get sampling */
					hwndCntl = GetDlgItem(hDlg, 1009);
					sampling = (WORD) SendMessage(hwndCntl, CB_GETCURSEL, 0, 0L) *2  + 3;

               /* get number of steps */
					hwndCntl = GetDlgItem(hDlg, 1010);
               GetWindowText(hwndCntl, szDisplay, 24);
					steps = atoi(szDisplay);

               /* get check box */
					hwndCntl = GetDlgItem(hDlg, 1011);
               nUnpolarized = (WORD) SendMessage (hwndCntl, BM_GETCHECK, 0, 0L);

					EndDialog(hDlg, wParam);
					return TRUE;

				case IDCANCEL:
            	if (lParam)
               	{
                  }
					EndDialog(hDlg, wParam);
					return TRUE;

            case 1011:
               /* toggle check mark */
					hwndCntl = GetDlgItem(hDlg, 1011);
					SendMessage (hwndCntl, BM_SETCHECK, (WORD)
               	!SendMessage (hwndCntl, BM_GETCHECK, 0, 0L), 0L);
					return TRUE;

				}
		}
	return FALSE;
	}

