//------------------------------------------------------------------------------------------------+
//                                                                                                |
//                                   SonicR FFCal Panel.mq4                                       |
//                                                                                                |
//------------------------------------------------------------------------------------------------+
#property copyright "Copyright @ 2012 traderathome"
#property link      "email: traderathome@msn.com" 

/*=================================================================================================
Overview, _v2:

This is a special version of the FFCAL.mq4 indicator designed especially for the Sonic R. System.
It places a panel in the lower left corner of the chart in which are displayed up to four news
releases listed on the Forex Factory Calendar.

The time, title and ranking by color of the releases are shown.  The time of releases is important 
because the market frequently holds price moves until after important releases come out.  The title 
of the release, and it's ranking by color, is important because the variety of low impact releases 
frequently have no effect on price, whereas the variety of high impact releases can trigger a big 
price move.                   

All three impact level events are displayed (High, Medium, Low) with the option to not show Medium
and Low impact releases.  Titles are color coded to signifiy the impact level because the impact 
level name is not displayed.  The Previous/Forecast data is not displayed either because it is the 
timing of news that is important (market volatility event) and not contents (prices can go either
way regardless of specifics released).  The vertical display and second alert are removed, but one 
alert remains.

Prioritization of events is fully automated and two more event labels are added to help avoid
surprises.  When two or more events occur simultaneously, only one event of the highest impact
displays unless there are multiple high impact events.  In that case the multple high impact 
events are displayed.  When 2nd, 3rd or 4th events are not scheduled, text noting that appears.  
A current day Bank Holiday will remain displayed in the first label until the Bank Holiday is 
over.  You can show events for any pair on any chart.  For example, you can show  a CNY (China) 
event on a AUDUSD chart.       
    
What is the "Broker_Watermark" input about?  A broker may have their name appear in pictures of 
MT4 charts.  This Watermark is typically in the lower left corner of the chart picture and will
appear in corner 2 of the chart itself if there are no chart sub-windows being used.  If this is
the case with your broker, to keep the Watermark from obscuring the FFCal display, select "true" 
for this input.  Then if the chart contains no sub-window, the background automatically increases 
in height and the text within is raised.  This creates the space needed below the FFCal text for 
the Watermark.

You can select a range of TFs for the display of this indicator, so it automatically will not 
display on a chart TF outside that range.  The indicator can be turned on/off without having 
to remove it from the chart, thereby preserving your chart settings. 

Changes from previous release 04-04-2012 to current release 05-01-2012:
01 - Corrected errors in coding of prioritization of previous and current/future events. 
02 - Revised order of External Inputs.
  
                                                                       - Traderathome, 05-01-2012
--------------------------------------------------------------------------------------------------
ACKNOWLEDGEMENTS:

derkwehler and other contributors - the core code of the FFCal indicator,
                                    FFCal_v20 dated 07/07/2009, Copyright @ 2006 derkwehler 
                                    http://www.forexfactory.com/showthread.php?t=19293
                                    email: derkwehler@gmail.com  
                                                                     
=================================================================================================*/	
 
 
//+-----------------------------------------------------------------------------------------------+
//| Indicator Global Inputs                                                                       |
//+-----------------------------------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1  CLR_NONE

#define TITLE		0
#define COUNTRY   1
#define DATE		2
#define TIME		3
#define IMPACT		4
#define FORECAST	5
#define PREVIOUS	6

/*-------------------------------------------------------------------------------------------------
Suggested Colors:                    White Charts          Black Charts

FFCal_Title                          Black                 C'188,188,188'
News_Low_Impact                      Green                 LimeGreen
News_Medium_Impact                   MediumBlue            CornflowerBlue
News_High_Impact                     Crimson               Red
Bank_Holiday_Color                   DarkOrchid            Orchid
Remarks_Color                        DarkGray              Gray      
Background_Color_                    White                 Black
-------------------------------------------------------------------------------------------------*/


//global external inputs---------------------------------------------------------------------------
extern string Part_1                          = "Indicator Display Controls:";
extern bool   Indicator_On                    = true;
extern int    Display_Min_TF                  = 1;
extern int    Display_Max_TF                  = 43200;
extern string TF_Choices_1                    = "M1 - H4 =  1, 5, 15, 30, 60, 240";
extern string TF_Choices_2                    = "D  W  M =  1440,  10080,  43200";

extern string __                              = "";
extern string Part_2                          = "Headline Display Settings:";
extern color  FFCal_Title 	                   = Black; 
extern color  Low_Impact_News_Color           = Green;
extern bool   Low_Impact_News_On              = true;             
extern color  Medium_Impact_News_Color        = MediumBlue;
extern bool   Medium_Impact_News_On           = true;       
extern color  High_Impact_News_Color          = Crimson;
extern color  Bank_Holiday_Color              = DarkOrchid;  
extern bool   Bank_Holiday_On                 = true;
extern color  Remarks_Color                   = DarkGray;     
extern color  Background_Color_               = White; 
extern bool   Broker_Watermark                = true;  //Raise display for Watermark 
extern int	  Alert_Minutes_Before            = 0;	    //Set to "0" for no Alert
extern int	  Offset_Hours	                   = 0;     //Set to "0" to not adjust time/DST settings

extern string ___                             = "";
extern string Part_3                          = "Other Currency News Settings:";
extern bool	  Show_USD_News                   = false; //"true" = USD news on non-USD pair charts 
extern bool	  Show_EUR_News                   = false; 
extern bool	  Show_GBP_News                   = false;
extern bool	  Show_NZD_News                   = false;
extern bool	  Show_JPY_News                   = false;
extern bool	  Show_AUD_News                   = false;
extern bool	  Show_CAD_News                   = false; 
extern bool	  Show_CHF_News                   = false;
extern bool	  Show_CNY_News                   = false;

//global buffers and variables---------------------------------------------------------------------
bool        FLAG_deinit, skip; 
bool        FLAG_done0, FLAG_done1, FLAG_done2, FLAG_done3; 
bool        FLAG_none0, FLAG_none1, FLAG_none2, FLAG_none3; 
int         BankIdx1;
color       TxtColorNews;
datetime    newsTime;
double   	ExtMapBuffer0[];     // Contains (minutes until) each news event
int 	      xmlHandle, BoEvent, finalend, end, begin, minsTillNews, tmpMins, idxOfNext, dispMinutes[9];
int         newsIdx, next, nextNewsIdx, dispMins, Days, Hours, Mins;
int         F1,F2,i,curY,W,Box,x1,x2,x3,y1,y2,y3,index;
int         WebUpdateFreq = 240; // 240 Minutes between web updates to not overload FF server
int         TxtSize       = 7;   
int         TitleSpacer   = 7;
int         EventSpacer   = 4; 
int         curX          = 3;       
static int	PrevMinute    = -1;
static bool NeedToGetFile = false;
string 		xmlFileName;
string	   sUrl = "http://www.forexfactory.com/ff_calendar_thisweek.xml"; //original
string   	myEvent,mainData[100][7], sData, csvoutput, sinceUntil, TimeStr;
string    	G,pair, cntry1, cntry2, dispTitle[9], dispCountry[9], dispImpact[9],event[4];
string 	   sTags[7] = { "<title>", "<country>", "<date><![CDATA[", "<time><![CDATA[", "<impact><![CDATA[", "<forecast><![CDATA[", "<previous><![CDATA[" };
string 	   eTags[7] = { "</title>", "</country>", "]]></date>", "]]></time>", "]]></impact>", "]]></forecast>", "]]></previous>" };
string      Text_Style = "Arial";     
string      box1    = "[FFCal] Box1";
string      box2    = "[FFCal] Box2";
string      News1   = "[FFCal] News1";
string      News2   = "[FFCal] News2";
string      News3   = "[FFCal] News3";
string      News4   = "[FFCal] News4";
string      Sponsor = "[FFCal] Sponsor";  

//+-----------------------------------------------------------------------------------------------+
//| Indicator Initialization                                                                      |
//+-----------------------------------------------------------------------------------------------+
int init()
   {
	//Make sure we are connected.  Otherwise exit.   
   //With the first DLL call below, the program will exit (and stop) automatically after one alert. 
   if ( !IsDllsAllowed() ) 
      {
      Alert("FFCal Headlines: Check 'Allow DLL Imports'");   
      } 
         
   FLAG_deinit = false;
    
	SetIndexBuffer(0, ExtMapBuffer0);
   SetIndexStyle(0, DRAW_NONE);		
   IndicatorShortName("FFCal");  	  	   	  		
   	  		
	return(0);
   }
   
//+-----------------------------------------------------------------------------------------------+
//| Indicator De-initialization                                                                   |
//+-----------------------------------------------------------------------------------------------+
int deinit()
   {         
   int obj_total= ObjectsTotal();  
   for (i= obj_total; i>=0; i--) {
      string name= ObjectName(i);
      if (StringSubstr(name,0,7)=="[FFCal]") {ObjectDelete(name);}} 
 	  
	//If xml file exists we need to delete it 
	xmlFileName = GetXmlFileName();
	//File does not exist if FileOpen returns -1 	
	xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ|FILE_WRITE);
	if (xmlHandle >= 0)
	   {
		//Since file exists, close and delete it
		FileClose(xmlHandle);		
		FileDelete(xmlFileName);
	   } 
	   
	//Comment (" "); 	     
	return(0);
   }
  
//+-----------------------------------------------------------------------------------------------+
//| Indicator Start                                                                               |
//+-----------------------------------------------------------------------------------------------+  
int start()
   {
   //If Indicator is "Off" or chart is out of range deinitialize only once, not every tick.
   if((!Indicator_On) || ((Period() < Display_Min_TF) || (Period() > Display_Max_TF)))        
      {
      if (!FLAG_deinit)  {deinit(); FLAG_deinit = true;} 
      return(0);
      }    
     
   //Otherwise indicator is "On", chart TF is in display range.  Proceed.  
   FLAG_deinit = false;
   
	//Check if the XML file exists.  If not, set a flag showing the need to get it.
	xmlFileName = GetXmlFileName();
	xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ);
   //File exists if FileOpen return is >=0 	
	if (xmlHandle >= 0) {FileClose(xmlHandle); NeedToGetFile = false;}
	//File does not exist if FileOpen return is -1 	
	else NeedToGetFile = true;
	
	//----------------------------------------------------------------------------------------------
	//WebUpdates New method: Use global variables so that when put on multiple charts, it 
	//will not update overly often; only first time and every 4 hours	per "WebUpdateFreq".		
  	if (NeedToGetFile || GlobalVariableCheck("LastUpdateTime") == false || 
  		(TimeCurrent() - GlobalVariableGet("LastUpdateTime")) > WebUpdateFreq)
		{	
		GrabWeb(sUrl, sData);		
   	//if time for web update, delete existing file if it exists	
	   xmlFileName = GetXmlFileName();
	   xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ|FILE_WRITE);
	   //File exists if FileOpen return >=0. 
	   if (xmlHandle >= 0) {FileClose(xmlHandle); FileDelete(xmlFileName);}	   		

		//Open new XML.  Write the ForexFactory page contents to a .htm file.  Close new XML.
		xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_WRITE);		   
		FileWriteString(xmlHandle, sData, StringLen(sData));
		FileClose(xmlHandle);
		
		//Find the XML end tag to ensure a complete page was downloaded.
		end = StringFind(sData, "</weeklyevents>", 0);
		//End of file tag is not found if return -1 (or, "end <=0" in this case).
		if (!end >= 0) {Alert("FFCal Error - Web page download was not complete!"); return(false);}
		else {GlobalVariableSet("LastUpdateTime", TimeCurrent());} // set global to time of last update			
		}
		
	//----------------------------------------------------------------------------------------------
	//Perform remaining checks once per minute (Refreshing News from XML file)
	if (Minute() == PrevMinute) return (true);
	PrevMinute = Minute();

	//Init the buffer array to zero just in case
	ArrayInitialize(ExtMapBuffer0, 0);
	
	//Open, read and close the XML file
	xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ);
	//Avg. file length == ~7K, so 65536 should always read whole file
	sData = FileReadString(xmlHandle, 65536);	
   if (StringLen(sData) < FileSize(xmlHandle)) sData = sData + FileReadString(xmlHandle, FileSize(xmlHandle));		
	if (xmlHandle > 0) FileClose(xmlHandle);

	//Get the currency pair, and split it into the two countries
	pair = Symbol();
	cntry1 = StringSubstr(pair, 0, 3);
	cntry2 = StringSubstr(pair, 3, 3);

	//Clear prioritization data
	BankIdx1   = 0; 
	FLAG_done0 = false; 
   FLAG_done1 = false;  
   FLAG_done2 = false;
   FLAG_done3 = false;
   FLAG_none0 = false;    
   FLAG_none1 = false; 
   FLAG_none2 = false;
   FLAG_none3 = false;  
	for (i=0; i<=9; i++)
	   {
	   dispTitle[i]   = "";
	   dispCountry[i] = "";
	   dispImpact[i] 	= "";
	   dispMinutes[i]	= 0;	
      }

	//Parse the XML file looking for an event to report		
	newsIdx = 0;
	nextNewsIdx = -1;	
	tmpMins = 10080;	// (a week)
	BoEvent = 0;
	while (true)
   	{
		BoEvent = StringFind(sData, "<event>", BoEvent);
		if (BoEvent == -1) break;			
		BoEvent += 7;	
		next = StringFind(sData, "</event>", BoEvent);
		if (next == -1) break;	
		myEvent = StringSubstr(sData, BoEvent, next - BoEvent);
		BoEvent = next;		
		begin = 0;
		skip = false;
		for (i=0; i < 7; i++)
		   {
			mainData[newsIdx][i] = "";
			next = StringFind(myEvent, sTags[i], begin);			
			// Within this event, if tag not found, then it must be missing; skip it
			if (next == -1) continue;
			else
			   {
				// We must have found the sTag okay...
				begin = next + StringLen(sTags[i]);		   	// Advance past the start tag
				end = StringFind(myEvent, eTags[i], begin);	// Find start of end tag
				//Get data between start and end tag
				if (end > begin && end != -1) {mainData[newsIdx][i] = StringSubstr(myEvent, begin, end - begin);}
			   }
		   }//End "for" loop
	
		//Test against filters that define whether we want to skip this particular announcement
      //Look for a Bank Holiday for current day
      
		if ( (Bank_Holiday_On &&  BankIdx1 == 0) &&
			(mainData[newsIdx][IMPACT] == "Holiday") &&			   		   
		   ((cntry1 == mainData[newsIdx][COUNTRY]) || 
		   (cntry2 == mainData[newsIdx][COUNTRY]) ||
		   (Show_USD_News && mainData[newsIdx][COUNTRY] == "USD") || 
			(Show_EUR_News && mainData[newsIdx][COUNTRY] == "EUR") || 
			(Show_GBP_News && mainData[newsIdx][COUNTRY] == "GBP") || 
			(Show_NZD_News && mainData[newsIdx][COUNTRY] == "NZD") || 
			(Show_JPY_News && mainData[newsIdx][COUNTRY] == "JPY") || 
			(Show_AUD_News && mainData[newsIdx][COUNTRY] == "AUD") || 
			(Show_CAD_News && mainData[newsIdx][COUNTRY] == "CAD") || 
			(Show_CHF_News && mainData[newsIdx][COUNTRY] == "CHF") || 
			(Show_CNY_News && mainData[newsIdx][COUNTRY] == "CNY") ))
		   {
		   newsTime = StrToTime(MakeDateTime(mainData[newsIdx][DATE], mainData[newsIdx][TIME]));
			minsTillNews = (newsTime - TimeGMT()) / 60;			
			//Only capture the current day Bank Holiday
			if ((minsTillNews > -1440) && (minsTillNews <= 0)) 
			   {
			   BankIdx1       = 1;			      
			   dispCountry[7] = mainData[newsIdx][COUNTRY];
			   dispMinutes[7] = minsTillNews;
			   dispTitle[7]	=  "Start " + mainData[newsIdx][TITLE];
			   dispImpact[7]  = "Holiday";	
				}			   				   
		   }
		   						
		else if ((cntry1 != mainData[newsIdx][COUNTRY] && cntry2 != mainData[newsIdx][COUNTRY]) &&
			((!Show_USD_News || mainData[newsIdx][COUNTRY] != "USD") && 
			(!Show_EUR_News || mainData[newsIdx][COUNTRY] != "EUR") && 
			(!Show_GBP_News || mainData[newsIdx][COUNTRY] != "GBP") && 
			(!Show_NZD_News || mainData[newsIdx][COUNTRY] != "NZD") && 
			(!Show_JPY_News || mainData[newsIdx][COUNTRY] != "JPY") && 
			(!Show_AUD_News || mainData[newsIdx][COUNTRY] != "AUD") && 
			(!Show_CAD_News || mainData[newsIdx][COUNTRY] != "CAD") && 
			(!Show_CHF_News || mainData[newsIdx][COUNTRY] != "CHF") && 
			(!Show_CNY_News || mainData[newsIdx][COUNTRY] != "CNY")))
			{skip = true;}	
			
		else if ((!Medium_Impact_News_On) && 
		   (mainData[newsIdx][IMPACT] == "Medium"))
		   {skip = true;} 
		   														   
		else if ((!Low_Impact_News_On) && 
		   (mainData[newsIdx][IMPACT] == "Low"))
		   {skip = true;} 
		   
		else if ((!Bank_Holiday_On) &&		
	      (mainData[newsIdx][IMPACT] == "Holiday"))
			{skip = true;}	
			
   	else if ((mainData[newsIdx][TIME] == "All Day" && mainData[newsIdx][TIME] == "") || 
		   (mainData[newsIdx][TIME] == "Tentative" && mainData[newsIdx][TIME] == "")     ||
		  	(mainData[newsIdx][TIME] == ""))
		  	{skip = true;}			  	
		    				  	 				  	 
		//If not skipping this event, then log time to event it into ExtMapBuffer0
		if (!skip)
		   {   
			//If we got this far then we need to calc the minutes until this event
			//First, convert the announcement time to seconds (in GMT)
			newsTime = StrToTime(MakeDateTime(mainData[newsIdx][DATE], mainData[newsIdx][TIME]));			
			// Now calculate the minutes until this announcement (may be negative)
			minsTillNews = (newsTime - TimeGMT()) / 60;
			
         //If this is a Bank Holiday current or past event, skip it by changing time to 2 days back
         if ((StringFind(mainData[newsIdx][TITLE], "Bank Holiday", StringLen(mainData[newsIdx][TITLE])-12) != -1) &&
            (minsTillNews <= 0))
            {
            minsTillNews = minsTillNews - 2880;
            }
            
			//At this point, only events applicable to the pair ID/Symbol are being processed:
			//Find the most recent past event.  Do this by incrementing idxOfNext for each event 
			//with a past time, (i.e. minsTillNews < 0).  When coming upon the first event with 
			//minsTillNews > 0, idxOfNext is not incremented, and therefore continues to be for 
			//the most recent past event.  It does not get incremented again until the absolute 
			//value of the time since this most recent past event exceeds the time to the next
			//future event.
			
			if (minsTillNews < 0 || MathAbs(tmpMins) > minsTillNews)	{idxOfNext = newsIdx; tmpMins	= minsTillNews;}	
						
			//Do alert if user has enabled
			if (Alert_Minutes_Before != 0 && minsTillNews == Alert_Minutes_Before)
				Alert(Alert_Minutes_Before, " minutes until news for ", pair, ": ", mainData[newsIdx][TITLE]);
						
			//ExtMapBuffer0 contains the time UNTIL each announcement (can be negative)
			//e.g. [0] = -372; [1] = 25; [2] = 450; [3] = 1768 (etc.)
			ExtMapBuffer0[newsIdx] = minsTillNews;
			
			newsIdx++;
		   }//End "skip" routine
	   }//End "while" routine
	   
	//----------------------------------------------------------------------------------------------
   //Cycle thru the range of "newsIdx" prioritizing events for display.
	for (i=0; i < newsIdx; i++)
	   {
      //The 1st event to be displayed is either a past event, or an upcoming event, whichever is the
      //most close in time.  If the 1st event is a past event, then look at the three previous past
      //events.  For any of them that occurred at the same time as the 1st event, choose for display
      //the most recent one with a higher impact.  If none have a higher impact, then stay with the
      //1st event.
      
      //Get 4th previous item:
      if (i == idxOfNext-3) 
         {    
			dispTitle[6]	   = mainData[i][TITLE];
			dispCountry[6] 	= mainData[i][COUNTRY];
			dispImpact[6]  	= mainData[i][IMPACT];
			dispMinutes[6] 	= ExtMapBuffer0[i];      
         }      
      //Get 3rd previous item:
      if (i == idxOfNext-2) 
         {      
			dispTitle[5]	   = mainData[i][TITLE];
			dispCountry[5] 	= mainData[i][COUNTRY];
			dispImpact[5]  	= mainData[i][IMPACT];
			dispMinutes[5] 	= ExtMapBuffer0[i];      
         }
      //Get 2nd previous item:   
      if (i == idxOfNext-1) 
         {   
			dispTitle[4]	   = mainData[i][TITLE];
			dispCountry[4] 	= mainData[i][COUNTRY];
			dispImpact[4]  	= mainData[i][IMPACT];
			dispMinutes[4] 	= ExtMapBuffer0[i];      
         }  
      //Get previous/current items:        
      if (i == idxOfNext)  
         {
         dispTitle[0]	   = mainData[i][TITLE];
			dispCountry[0] 	= mainData[i][COUNTRY];
			dispImpact[0]  	= mainData[i][IMPACT];
			dispMinutes[0] 	= ExtMapBuffer0[i];
         //If idxOfNext is a previous event, then compare to 2nd, 3rd and 4th previous events.
         //If none of these three also previous events have the same time and a higher impact,
         //stay with the most recent previous event ([0]):  			         
         if (dispMinutes[0] <= 0) 
            {
	         //if time [0] = [4] and [4] is > impact than [0], then [4] becomes 1st event [0]
	         //In other words, if 2nd previous event back is of higher impact use it:
	         if ((dispMinutes[0] == dispMinutes[4]) &&		
	         ((dispImpact[0] == "Medium" && dispImpact[4] == "High")  ||
			   (dispImpact[0]  == "Low"    && dispImpact[4] == "High")  ||
			   (dispImpact[0]  == "Low"    && dispImpact[4] == "Medium")))
		 	      {		 	   
		   	   dispTitle[0]	= dispTitle[4];
			      dispCountry[0] = dispCountry[4];
			      dispImpact[0]  = dispImpact[4];
			      dispMinutes[0] = dispMinutes[4];
			      }	                                       									
		      //if time [0] = [5] and [5] is > impact than [0], then [5] becomes 1st event [0]
		      //In other words, if 3rd previous event back is of higher impact use it: 
	         else if ((dispMinutes[0] == dispMinutes[5]) &&		
	         ((dispImpact[0] == "Medium" && dispImpact[5] == "High")  ||
			   (dispImpact[0]  == "Low"    && dispImpact[5] == "High")  ||
			   (dispImpact[0]  == "Low"    && dispImpact[5] == "Medium")))
		 	      {		 	   
		      	dispTitle[0]   = dispTitle[5];
			      dispCountry[0] = dispCountry[5];
			      dispImpact[0]  = dispImpact[5];
			      dispMinutes[0] = dispMinutes[5];						   
               }
            //if time [0] = [6] and [6] is  > impact than [0], then [6] becomes 1st event [0]
            //In other words, if 4th previous event back is of higher impact use it:
	         else if ((dispMinutes[0] == dispMinutes[6]) &&		
	         ((dispImpact[0] == "Medium" && dispImpact[6] == "High")  ||
			   (dispImpact[0]  == "Low"    && dispImpact[6] == "High")  ||
			   (dispImpact[0]  == "Low"    && dispImpact[6] == "Medium")))
		 	      {		 	   
		      	dispTitle[0]   = dispTitle[6];
			      dispCountry[0] = dispCountry[6];
			      dispImpact[0]  = dispImpact[6];
			      dispMinutes[0] = dispMinutes[6];						   
               }   					   
            }
         }   
         
		//---------------------------------------------------------------- 	            
      //Now that 1st event[0] is initialized, go thru rest of items, prioritizing.  
		if (i >= idxOfNext+1)  
		   {  
         dispTitle[6]	= mainData[i][TITLE];
			dispCountry[6] = mainData[i][COUNTRY];
			dispImpact[6]  = mainData[i][IMPACT];
			dispMinutes[6] = ExtMapBuffer0[i];
			//If 1st event [0] is not done with prioritization, and         		   
			//if time [i] = [0] and [i] has > impact than [0] then [i] becomes 1st event [0].
	   	//Otherwise, if time [i] > [0] then initialize [i] as 2nd event [1]: 
	   	if (!FLAG_done0) 
	   	   { 
			   if ((dispMinutes[0] == dispMinutes[6]) && 			
	            ((dispImpact[0]  == "Medium" && dispImpact[6] == "High")  ||
			      (dispImpact[0]   == "Low"    && dispImpact[6] == "High")  || 
			      (dispImpact[0]   == "Low"    && dispImpact[6] == "Medium")))
		 	      {
               dispTitle[0]	  = dispTitle[6];
			      dispCountry[0]   = dispCountry[6];
			      dispImpact[0]    = dispImpact[6];
			      dispMinutes[0]   = dispMinutes[6];	 	   		 	   		 	   			
			      }		      
		      else if ((dispMinutes[0] < dispMinutes[6]) ||
		         ((dispMinutes[0] == dispMinutes[6]) && (dispImpact[6] == "High")) )    
		         {
               dispTitle[1]	  = dispTitle[6];
			      dispCountry[1]   = dispCountry[6];
			      dispImpact[1]    = dispImpact[6];
			      dispMinutes[1]   = dispMinutes[6];
			      FLAG_done0 = true;
			      continue;
		         }		         
		      }
		   //If 1st event [0] is done prioritization, but 2nd event [1] is not, and   
			//if time [i] = [1] and [i] has > impact than [1], then [i] becomes 2nd event [1].
			//Otherwise, if time [i] > [1] then intialize [i] as 3rd event [2]: 
         if ((FLAG_done0) && (!FLAG_done1)) 
		      {			 			   	
			   if ((dispMinutes[1] == dispMinutes[6]) && 		
	            ((dispImpact[1]  == "Medium" && dispImpact[6] == "High")  ||
			      (dispImpact[1]   == "Low"    && dispImpact[6] == "High")  || 
			      (dispImpact[1]   == "Low"    && dispImpact[6] == "Medium")))
		 	      {
               dispTitle[1]	   = dispTitle[6];
			      dispCountry[1] 	= dispCountry[6];
			      dispImpact[1]  	= dispImpact[6];
			      dispMinutes[1] 	= dispMinutes[6];	
			      }
			   else if ((dispMinutes[1] < dispMinutes[6]) ||
		         ((dispMinutes[1] == dispMinutes[6]) && (dispImpact[6] == "High")) )  			   		    
			      {
               dispTitle[2]	   = dispTitle[6];
			      dispCountry[2] 	= dispCountry[6];
			      dispImpact[2]  	= dispImpact[6];
			      dispMinutes[2] 	= dispMinutes[6];					      
			      FLAG_done1 = true;
			      continue;
			      }   
			   }
	      //If 1st event [0] and 2nd event [1] are done, but 3rd event [2] is not, and
			//if time [i] = [2] and [i] has > impact than [2], then [i] becomes 3rd event [2].
		   //Otherwise, if time [i] > [2] then intialize [i] as 4th event [3]:  	
         if ((FLAG_done0) && (FLAG_done1) && (!FLAG_done2)) 
		      {						   
			   if ((dispMinutes[2] == dispMinutes[6]) && 		
	            ((dispImpact[2]  == "Medium" && dispImpact[6] == "High")  ||
			      (dispImpact[2]   == "Low"    && dispImpact[6] == "High")  || 
			      (dispImpact[2]   == "Low"    && dispImpact[6] == "Medium")))
		 	      {
               dispTitle[2]	   = dispTitle[6];
			      dispCountry[2] 	= dispCountry[6];
			      dispImpact[2]  	= dispImpact[6];
			      dispMinutes[2] 	= dispMinutes[6];		   			        		 	   		 	   		 	   			
			      }
			   else if ((dispMinutes[2] < dispMinutes[6]) ||
		         ((dispMinutes[2] == dispMinutes[6]) && (dispImpact[6] == "High")) )  			    
			      {
               dispTitle[3]	   = dispTitle[6];
			      dispCountry[3] 	= dispCountry[6];
			      dispImpact[3]  	= dispImpact[6];
			      dispMinutes[3] 	= dispMinutes[6];					      
			      FLAG_done2 = true;
			      continue;
			      }  
			   }
         //If 1st, 2nd, and 3rd events are done, but 4th event [3] is not, and
			//if time [i] = [3] and [i] has > impact than [3], then [i] becomes 4th event [3].
			//Otherwise, prioritizing is finished:  	
         if ((FLAG_done0) && (FLAG_done1) && (FLAG_done2) && (!FLAG_done3)) 
		      {						   
			   if ((dispMinutes[3] == dispMinutes[6])  &&
	            ((dispImpact[3]  == "Medium" && dispImpact[6] == "High")  ||
			      (dispImpact[3]   == "Low"    && dispImpact[6] == "High")  || 
			      (dispImpact[3]   == "Low"    && dispImpact[6] == "Medium")))     	
		 	      {
               dispTitle[3]	   = dispTitle[6];
			      dispCountry[3] 	= dispCountry[6];
			      dispImpact[3]  	= dispImpact[6];
			      dispMinutes[3] 	= dispMinutes[6];  			        		 	   		 	   		 	   			
			      }			      			      		         			      
			   //Otherwise, prioritizing is finished:    
			   else
			      {			     
			      FLAG_done3 = true;
			      } 			      			   			   
			   }
						    			
 			//If all four event items are prioritized, exit loop.	   			   							   			   
		   if ((FLAG_done0) && (FLAG_done1) && (FLAG_done2) && (FLAG_done3)) {break;} 
			}
			  
	   }//End prioritizing "for" loop	
	   
	   //Next, determine if any events are out of sequence in time, or are duplicates in title 
	   //and are within the same 24 hour period.  If so, eliminate the higher event item by
	   //setting the flag to not show the item.
	   //Check 1st and 2nd items.  
		if (((dispTitle[0]==dispTitle[1]) && (dispMinutes[0]+ 1440 > dispMinutes[1])) ||
		   (dispMinutes[0] > dispMinutes[1]))
			{
			{FLAG_none1  = true;}	
			}			 	   	
      //Also check 1st and 3rd, and 2nd and 3rd items. 
		if (((dispTitle[0]==dispTitle[2]) && (dispMinutes[0]+ 1440 > dispMinutes[2])) ||  
			((dispTitle[1]==dispTitle[2]) && (dispMinutes[1]+ 1440 > dispMinutes[2]))  ||
			(dispMinutes[0] > dispMinutes[2]) || (dispMinutes[1] > dispMinutes[2]))
			{
			{FLAG_none2  = true;}	
			} 				     
      //Also check 1st and 4th, and 3rd and 4th items. 
		if (((dispTitle[0]==dispTitle[3]) && (dispMinutes[0]+ 1440 > dispMinutes[3])) ||  
			((dispTitle[2]==dispTitle[3]) && (dispMinutes[2]+ 1440 > dispMinutes[3]))  ||
			(dispMinutes[0] > dispMinutes[3]) || (dispMinutes[2] > dispMinutes[3]))
			{
			{FLAG_none3  = true;}	
			}
			
	   //Check if 1st event[0] is more than half a day old and no 2nd event is scheduled.
	   //If so, eliminate the 1st event[0].	
	   if ((dispMinutes[0] < -720) && (dispMinutes[1] == 0 )) 
			{
			{FLAG_none0  = true;}	
			}
					
		//Be sure no "FLAG_none" remains false if a lower one turned to true
		if (FLAG_none0) 
		   {
		   FLAG_none1  = true;
		   FLAG_none2  = true;
		   FLAG_none3  = true;
		   }
		else if (FLAG_none1) 
		   {
		   FLAG_none2  = true;
		   FLAG_none3  = true;
		   }
		else if (FLAG_none2) 
		   {
		   FLAG_none3  = true;
		   }
	
		//Be sure to "FLAG_none" any with no country tag
		if (dispCountry[0] == "") {FLAG_none0 = true;}
		if (dispCountry[1] == "") {FLAG_none1 = true;}
		if (dispCountry[2] == "") {FLAG_none2 = true;}
		if (dispCountry[3] == "") {FLAG_none3 = true;}
		        
		//Check for current day Bank Holiday.  If there is one, then move all
      //events up one tier and insert the Bank Holiday into 1st event.
      if (BankIdx1 == 1)
		   {      
         dispTitle[3]	   = dispTitle[2];
			dispCountry[3] 	= dispCountry[2];
			dispImpact[3]  	= dispImpact[2];
			dispMinutes[3] 	= dispMinutes[2];
			FLAG_none3        = FLAG_none2;
		  
			dispTitle[2]	   = dispTitle[1];
			dispCountry[2] 	= dispCountry[1];
			dispImpact[2]  	= dispImpact[1];
			dispMinutes[2] 	= dispMinutes[1];
			FLAG_none2        = FLAG_none1;
			     	
         dispTitle[1]	   = dispTitle[0];
			dispCountry[1] 	= dispCountry[0];
			dispImpact[1]  	= dispImpact[0];
			dispMinutes[1] 	= dispMinutes[0];
			FLAG_none1        = FLAG_none0;
			     
         dispTitle[0]	   = dispTitle[7];
			dispCountry[0]    = dispCountry[7];
			dispImpact[0]  	= dispImpact[7];
			dispMinutes[0]    = dispMinutes[7];
			FLAG_none0        = false;
			}
      
	//---------------------------------------------------------------------------------------------
	//Go to subroutine to draw panel background and event labels.					
	OutputToChart();
			
	return (0);
   }
   
//+-----------------------------------------------------------------------------------------------+
//| Subroutine to get the name of the ForexFactory .xml file                                      |
//+-----------------------------------------------------------------------------------------------+    
string GetXmlFileName()
   {
	return (Month() + "-" + Day() + "-" + Year() + "-" + Symbol() + Period() + "-" + "FFCal.xml");
   }

//+-----------------------------------------------------------------------------------------------+
//| Indicator Routine For Normal Display                                                          |
//+-----------------------------------------------------------------------------------------------+  
void OutputToChart()
   {
   //Compose fourth event description line--------------------------------------------------------- 	           
   sinceUntil = "until ";
   dispMins = dispMinutes[3]+1; 
	if (dispMinutes[3] <= 0) {dispMins = dispMins - 1; sinceUntil = "since "; dispMins *= -1;} 	
   if (dispMins < 60) {TimeStr = dispMins + " mins ";}
	else // time is 60 minutes or more
	   {
		Hours = MathRound(dispMins / 60);
	   Mins = dispMins % 60;
	   if (Hours < 24) // less than a day: show hours and minutes 
		   {
			TimeStr = Hours + " hrs " + Mins + " mins ";
		   }
		else // days, hours, and minutes
		  	{
		  	Days = MathRound(Hours / 24);
		 	Hours = Hours % 24;
		  	TimeStr = Days + " days " + Hours + " hrs " + Mins + " mins ";
		  	}
	   }               	
   index = StringFind(TimeStr+sinceUntil+dispCountry[3], "since  mins", 0);  
   TxtColorNews = ImpactToColor(dispImpact[3]);	   		      	
	ObjectDelete(News4);       	
   ObjectCreate(News4, OBJ_LABEL, 0, 0, 0);
		if((index != -1) || (FLAG_none3)) 
		   {	        
		   ObjectSetText(News4, "(4)  Additional news events not scheduled", 
		      TxtSize, Text_Style, Remarks_Color);
		   event[4] = "(4)  Additional news events not scheduled";
		   }	           		                		            			            	            		   	   
	   else 
	      {
		   ObjectSetText(News4, TimeStr + sinceUntil + dispCountry[3] + 
		      ": " + dispTitle[3], TxtSize, Text_Style, TxtColorNews);
		   event[4] = TimeStr + sinceUntil + dispCountry[3] + ": " + dispTitle[3];
		   }
             
   //Compose third event description line--------------------------------------------------------- 	           
   sinceUntil = "until ";
   dispMins = dispMinutes[2]+1;
	if (dispMinutes[2] <= 0) {dispMins = dispMins - 1; sinceUntil = "since "; dispMins *= -1;}   	
   if (dispMins < 60) {TimeStr = dispMins + " mins ";}
	else // time is 60 minutes or more
	   {
		Hours = MathRound(dispMins / 60);
	   Mins = dispMins % 60;
	   if (Hours < 24) // less than a day: show hours and minutes 
		   {
			TimeStr = Hours + " hrs " + Mins + " mins ";
		   }
		else // days, hours, and minutes
		  	{
		  	Days = MathRound(Hours / 24);
		 	Hours = Hours % 24;
		  	TimeStr = Days + " days " + Hours + " hrs " + Mins + " mins ";
		  	}
	   }               	
   index = StringFind(TimeStr+sinceUntil+dispCountry[2], "since  mins", 0); 		      	
   TxtColorNews = ImpactToColor(dispImpact[2]);	 	      	
	ObjectDelete(News3);       	
   ObjectCreate(News3, OBJ_LABEL, 0, 0, 0);
		if((index != -1) || (FLAG_none2)) 
		   {	        
		   ObjectSetText(News3, "(3)  Additional news events not scheduled", 
		      TxtSize, Text_Style, Remarks_Color);
		   event[3] = "(3)  Additional news events not scheduled";
		   }	           		                		            			            	            		   	   
	   else 
	      {
		   ObjectSetText(News3, TimeStr + sinceUntil + dispCountry[2] + 
		      ": " + dispTitle[2], TxtSize, Text_Style, TxtColorNews);
		   event[3] = TimeStr + sinceUntil + dispCountry[2] + ": " + dispTitle[2];
		   }		   		  
           
	//Compose second event description line-------------------------------------------------------- 	           
   sinceUntil = "until ";
   dispMins = dispMinutes[1]+1;  
	if (dispMinutes[1] <= 0) {dispMins = dispMins - 1; sinceUntil = "since "; dispMins *= -1;} 	
   if (dispMins < 60) {TimeStr = dispMins + " mins ";}
	else // time is 60 minutes or more
	   {
	   Hours = MathRound(dispMins / 60);
	   Mins = dispMins % 60;
	   if (Hours < 24) // less than a day: show hours and minutes 
		   {
		   TimeStr = Hours + " hrs " + Mins + " mins ";
		   }
		else // days, hours, and minutes
		   {
		   Days = MathRound(Hours / 24);
			Hours = Hours % 24;
			TimeStr = Days + " days " + Hours + " hrs " + Mins + " mins ";
		   }
	   }               	
	index = StringFind(TimeStr+sinceUntil+dispCountry[1], "since  mins", 0); 		      	
   TxtColorNews = ImpactToColor(dispImpact[1]);	 	      	
	ObjectDelete(News2);       	
   ObjectCreate(News2, OBJ_LABEL, 0, 0, 0);
		if((index != -1) || (FLAG_none1)) 
		   {		       
		   ObjectSetText(News2, "(2)  Additional news events not scheduled", 
		      TxtSize, Text_Style, Remarks_Color);
		   event[2] = "(2)  Additional news events not scheduled";
		   }	           		                		            			            	            		   	   
	   else 
	      {
		   ObjectSetText(News2, TimeStr + sinceUntil + dispCountry[1] + 
		      ": " + dispTitle[1], TxtSize, Text_Style, TxtColorNews);
		   event[2] = TimeStr + sinceUntil + dispCountry[1] + ": " + dispTitle[1];
		   }		  
         
	//Compose first event description line---------------------------------------------------------  
	//If time is 0 or negative, we want to say "xxx mins SINCE ... news event", 
	//else say "UNTIL ... news event"
	sinceUntil = "until ";
	dispMins = dispMinutes[0]+1;  //dispMins "*= -1" = multiply by "-1" 
	if (dispMinutes[0] <= 0) {dispMins = dispMins - 1; sinceUntil = "since "; dispMins *= -1;}	      
	if (dispMins < 60) {TimeStr = dispMins + " mins ";}
	else // time is 60 minutes or more
	   {
		Hours = MathRound(dispMins / 60);
		Mins = dispMins % 60;
		if (Hours < 24) // less than a day: show hours and minutes
		   {
		   TimeStr = Hours + " hrs " + Mins + " mins ";
		   }
		else  // days, hours, and minutes
		   {
		   Days = MathRound(Hours / 24);
			Hours = Hours % 24;
			TimeStr = Days + " days " + Hours + " hrs " + Mins + " mins ";
		   }
	   }	  		         
	index = StringFind(TimeStr+sinceUntil+dispCountry[0], "since  mins", 0); //Comment (index);	
	TxtColorNews = ImpactToColor(dispImpact[0]);	       	   
	ObjectDelete(News1);		         	    
	ObjectCreate(News1, OBJ_LABEL, 0, 0, 0);
		if((index != -1) || (FLAG_none0)) 
		   {	      
		   ObjectSetText(News1, "(1)  Additional news events not scheduled", 
		      TxtSize, Text_Style, Remarks_Color);
		   event[1] = "(1)  Additional news events not scheduled";
		   }			                  	         		         	
		else 
		   {
	   	ObjectSetText(News1, TimeStr + sinceUntil + dispCountry[0] + 
	   	   ": " + dispTitle[0], TxtSize, Text_Style, TxtColorNews);
	   	event[1] = TimeStr + sinceUntil + dispCountry[0] + ": " + dispTitle[0];
	   	}

   //Do background---------------------------------------------------------------------------------   
   x1          = 0; 
   x2          = 0;               
	y2          = 1;	     
	W           = WindowsTotal( );
	     
   //Automate Determination of Width of Background
   int ii;
   x1 = 0; for (i=0; i <= 3; i++) 
      {
      if(i == 0) {x1 = StringLen(event[i]);}
      else
         {
         if(StringLen(event[i]) > x1)
           {
           x1 = StringLen(event[i]);
           ii = i;
           }
         }  
      }  
   if(x1>138) x2 = x1-138+141;//x2 = starts where x1 characters stop
   else x2 = 141;
      	    
   //Set up to do background boxes 	               
   if(Broker_Watermark && W ==1) 
      {
      curY = 9;  
      Box  = 64;             
      curY = curY+12;
      G    = "gg"; 
      } 
   else
      {
      curY = 6; 
      Box  = 54; 
      x2   = x2 - 46;//compensate for more g's being used (46 per g?)
      G    = "ggg";
      }
                                    
   //Draws Background boxes    
   ObjectCreate(box1, OBJ_LABEL, 0, 0,0);
   ObjectSetText(box1, G, Box, "Webdings");          
   ObjectSet(box1, OBJPROP_CORNER, 2);
   ObjectSet(box1, OBJPROP_XDISTANCE, 0);       
   ObjectSet(box1, OBJPROP_YDISTANCE, 1);      
   ObjectSet(box1, OBJPROP_COLOR, Background_Color_);
   ObjectSet(box1, OBJPROP_BACK, true);

   ObjectCreate(box2, OBJ_LABEL, 0, 0,0);
   ObjectSetText(box2, G, Box, "Webdings");         
   ObjectSet(box2, OBJPROP_CORNER, 2);
   ObjectSet(box2, OBJPROP_XDISTANCE, x2);       
   ObjectSet(box2, OBJPROP_YDISTANCE, 1);      
   ObjectSet(box2, OBJPROP_COLOR, Background_Color_);
   ObjectSet(box2, OBJPROP_BACK, true);

   //Draw Event4
	ObjectSet(News4, OBJPROP_CORNER, 2);
	ObjectSet(News4, OBJPROP_XDISTANCE, curX);
	ObjectSet(News4, OBJPROP_YDISTANCE, curY); 	   	   	
   curY = curY + TxtSize + EventSpacer;
   
   //Draw Event3
	ObjectSet(News3, OBJPROP_CORNER, 2);
	ObjectSet(News3, OBJPROP_XDISTANCE, curX);
	ObjectSet(News3, OBJPROP_YDISTANCE, curY); 	   	   	
   curY = curY + TxtSize + EventSpacer; 
       
   //Draw Event2
	ObjectSet(News2, OBJPROP_CORNER, 2);
   ObjectSet(News2, OBJPROP_XDISTANCE, curX);
	ObjectSet(News2, OBJPROP_YDISTANCE, curY); 	   	   	
   curY = curY + TxtSize + EventSpacer;     
      
   //Draw Event1   
	ObjectSet(News1, OBJPROP_CORNER, 2);
	ObjectSet(News1, OBJPROP_XDISTANCE, curX);
	ObjectSet(News1, OBJPROP_YDISTANCE, curY);        	
   curY = curY + TxtSize + TitleSpacer;    
      	       
   //Finish with title-----------------------------------------------------------------------------
	ObjectDelete(Sponsor);         	     	         	
	ObjectCreate(Sponsor, OBJ_LABEL, 0, 0, 0);
 	ObjectSetText(Sponsor, "CAL HEADLINES:", TxtSize, "Verdana", FFCal_Title);
	ObjectSet(Sponsor, OBJPROP_CORNER, 2);
	ObjectSet(Sponsor, OBJPROP_XDISTANCE, curX);
	ObjectSet(Sponsor, OBJPROP_YDISTANCE, curY);          
                
	return (0);
   }

//+-----------------------------------------------------------------------------------------------+
//| Indicator Subroutine For Impact Color                                                         |
//+-----------------------------------------------------------------------------------------------+  
double ImpactToColor (string impact)
   {
	if (impact == "High") return (High_Impact_News_Color);
	else {if (impact == "Medium") return (Medium_Impact_News_Color);
	else {if (impact == "Low") return (Low_Impact_News_Color);
	else {if (impact == "Holiday") return (Bank_Holiday_Color); 
	else {return (Remarks_Color);} }}}  
   }

//+-----------------------------------------------------------------------------------------------+
//| Indicator Subroutine For Date/Time                                                            |
//+-----------------------------------------------------------------------------------------------+ 
string MakeDateTime(string strDate, string strTime)
   {
	//Print("Converting Forex Factory Time into Metatrader time..."); //added by MN
	//Converts forexfactory time & date into yyyy.mm.dd hh:mm
	int n1stDash = StringFind(strDate, "-");
	int n2ndDash = StringFind(strDate, "-", n1stDash+1);

	string strMonth = StringSubstr(strDate, 0, 2);
	string strDay = StringSubstr(strDate, 3, 2);
	string strYear = StringSubstr(strDate, 6, 4); 
   //strYear = "20" + strYear;
	
	int nTimeColonPos = StringFind(strTime, ":");
	string strHour = StringSubstr(strTime, 0, nTimeColonPos);
	string strMinute = StringSubstr(strTime, nTimeColonPos+1, 2);
	string strAM_PM = StringSubstr(strTime, StringLen(strTime)-2);

	int nHour24 = StrToInteger(strHour);
	if (strAM_PM == "pm" || strAM_PM == "PM" && nHour24 != 12) {nHour24 += 12;}
	if (strAM_PM == "am" || strAM_PM == "AM" && nHour24 == 12) {nHour24 = 0;}
 	string strHourPad = "";
	if (nHour24 < 10) strHourPad = "0";

	return(StringConcatenate(strYear, ".", strMonth, ".", strDay, " ", strHourPad, nHour24, ":", strMinute));
   }

//=================================================================================================
//===============================   Begin Imported Functions   ====================================
//=================================================================================================
// Main Webscraping function
// ~~~~~~~~~~~~~~~~~~~~~~~~~
// bool GrabWeb(string strUrl, string& strWebPage)
// returns the text of any webpage. Returns false on timeout or other error
// 
// Parsing functions
// ~~~~~~~~~~~~~~~~~
// string GetData(string strWebPage, int nStart, string strLeftTag, string strRightTag, int& nPos)
// obtains the text between two tags found after nStart, and sets nPos to the end of the second tag
//
// void Goto(string strWebPage, int nStart, string strTag, int& nPos)
// Sets nPos to the end of the first tag found after nStart 

bool bWinInetDebug = false;
int  hSession_IEType;
int  hSession_Direct;
int  Internet_Open_Type_Preconfig = 0;
int  Internet_Open_Type_Direct = 1;
int  Internet_Open_Type_Proxy = 3;
int  Buffer_LEN = 80;

#import "wininet.dll"
//Forces the request to be resolved by the origin server, even if a cached copy exists on the proxy.
#define INTERNET_FLAG_PRAGMA_NOCACHE    0x00000100 

//Does not add the returned entity to the cache. 
#define INTERNET_FLAG_NO_CACHE_WRITE    0x04000000 
 
//Forces a download of the requested file, object, or directory listing from the origin server, not from the cache.
#define INTERNET_FLAG_RELOAD            0x80000000 

int InternetOpenA(
	string 	sAgent,
	int		lAccessType,
	string 	sProxyName="",
	string 	sProxyBypass="",
	int 	lFlags=0);

int InternetOpenUrlA(
	int 	hInternetSession,
	string 	sUrl, 
	string 	sHeaders="",
	int 	lHeadersLength=0,
	int 	lFlags=0,
	int 	lContext=0);

int InternetReadFile(
	int 	hFile,
	string 	sBuffer,
	int 	lNumBytesToRead,
	int& 	lNumberOfBytesRead[]);

int InternetCloseHandle(
	int 	hInet);
	
#import

//-------------------------------------------------------------------------------------------------
int hSession(bool Direct)
   {
	string InternetAgent;
	if (hSession_IEType == 0)
	   {
		InternetAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461)";
		hSession_IEType = InternetOpenA(InternetAgent, Internet_Open_Type_Preconfig, "0", "0", 0);
		hSession_Direct = InternetOpenA(InternetAgent, Internet_Open_Type_Direct, "0", "0", 0);
	   }
	if (Direct) {return(hSession_Direct);}
	else {return(hSession_IEType);}
   }

//-------------------------------------------------------------------------------------------------
bool GrabWeb(string strUrl, string& strWebPage)
   {
	int   	hInternet;
	int		iResult;
	int   	lReturn[]	= {1};
	string 	sBuffer		= "                                                                                                                                                                                                                                                               ";	// 255 spaces
	int   	bytes;
	
	hInternet = InternetOpenUrlA(hSession(FALSE), strUrl, "0", 0, 
								INTERNET_FLAG_NO_CACHE_WRITE | 
								INTERNET_FLAG_PRAGMA_NOCACHE | 
								INTERNET_FLAG_RELOAD, 0);
								   
	if (hInternet == 0) return(false);
	Print("Reading URL: " + strUrl);	   //added by MN	
	iResult = InternetReadFile(hInternet, sBuffer, Buffer_LEN, lReturn);
	if (iResult == 0)  return(false);
	bytes = lReturn[0];
	strWebPage = StringSubstr(sBuffer, 0, lReturn[0]);
	
	//If there's more data then keep reading it into the buffer
	while (lReturn[0] != 0)
	   {
		iResult = InternetReadFile(hInternet, sBuffer, Buffer_LEN, lReturn);
		if (lReturn[0]==0) break;
		bytes = bytes + lReturn[0];
		strWebPage = strWebPage + StringSubstr(sBuffer, 0, lReturn[0]);
   	}
	Print("Closing URL web connection");   //added by MN
	iResult = InternetCloseHandle(hInternet);
	if (iResult == 0) return(false);		
	return(true);
   }

//===================================   Timezone Functions   ======================================
#import "kernel32.dll"
int  GetTimeZoneInformation(int& TZInfoArray[]);
#import
#define TIME_ZONE_ID_UNKNOWN   0
#define TIME_ZONE_ID_STANDARD  1
#define TIME_ZONE_ID_DAYLIGHT  2
int TZInfoArray[43];	
datetime TimeGMT() 
   {
	int DST = GetTimeZoneInformation(TZInfoArray);
	if (DST == 1) DST = 3600;
	else DST = 0;
	return( TimeLocal() + DST + (Offset_Hours * 3600) + (TZInfoArray[0] + TZInfoArray[42]) * 60 );
   }

//=================================================================================================
//=================================   End Imported Functions  =====================================
//=================================================================================================

//+-----------------------------------------------------------------------------------------------+
//| Indicator End                                                                                 |                                                        
//+-----------------------------------------------------------------------------------------------+