//------------------------------------------------------------------------------------------------+
//                                                                                                |
//                                      CalendarFX-I-A15.mq4                                      |
//                                                                    |
//------------------------------------------------------------------------------------------------+
#property copyright "Copyright @ 2014 traderathome, deVries, qFish, atstrader, rod178, ForexTaurus"
#property link      "http://ForexTaurus.blogspot.com" 

// modified June 4, 2015 by Forex Taurus
// added "Important News Caution" for ECB, FOMC, NFP, BOE, RBA, BOC, BOJ
// commented Print statements
// Added "Events Objects" as I find Newslines to be too noisy and cluttering the chart
//  
// modified June 3, 2015 by Forex Taurus
// added Next Up Event
// bug fix for deinit
// added "NewsLineDescription" to turn Object Descriptions for NewsLines On/Off

// modified May 21, 2015 by Forex Taurus
// added ShowSession Open
// added ObjectsEditable Paramter
// 
// modified May 12, 2015 by Forex Taurus
// added HistoryOn input parameter.  when off vertical lines/text will be deleted for past due events
//
// modified May 12, 2015 by Forex Taurus
// added SleepInSeconds for better performance
// added NewsLineTextSize Input to control size of NewsLineText, default = 25 characters
// added spacing for Multiple News Events at same time to prevent overlap
// added Notifications
// added EMails
// added AlertOn, NotificationOn, MailOn for selecting prefered alert method
// added Alert Parameters to FFCAL News Text

// modified May 8, 2015 by Forex Taurus
// Show Inputs upon Indicator Activation
// Fixed bug with background boxes


// MODIFIED rod178 July 2014
// added news lines and script to chart
// metdat@gmail.com 


//  UseAlternateSource.......False = Forex Factory calendar data (recommended), True = DailyFX calendar data

/*-------------------------------------------------------------------------------------------------

//   http://www.forexfactory.com/showthread.php?t=250544&page=20
// http://www.forexfactory.com/showthread.php?t=444542
// http://www.forexfactory.com/rss.php     // for the xML urls
User Notes:

This indicator is coded to run on MT4 Build 600.

This is a special version of the FFCal.mq4 indicator designed especially for the Sonic R. System.
It places a panel on the chart in which are displayed up to four news releases listed on the 
Forex Factory Calendar.  Significant changes are made since the last release.  These changes are
summarized at the bottom of these User Notes.

The time, title and ranking (by color) of the releases are shown.  

The time of a releases is important because the market frequently holds price moves until after 
important releases come out.  Also, Market Makers can prepare in advance for these moves.  The 
Market Makers and banks do know the essence of news and releases in advance, and there is no 
regulation against insider trading in the forex market.  Banks can place orders in advance of
releases and Market Makers can use the intervening time to move prices to fill those orders,
saving the move that will make profits on the orders until the time of the releases. 

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, or can cause Market Makers to start moving prices days in advance,
in preparations for big moves to be made in conjunction with those releases.                  

Of the three impact level events (High, Medium, Low) and Bank Holidays, you have the option to not 
show all but the High Impact events.  The Previous/Forecast data (available on the Forex Factory
Calendar) is not displayed because prices can go either way regardless of specifics released.  it 
is the timing of news that is important, as a market volatility event.  The vertical display and 
the second alert of the original FFCal. mq4 indicator 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.  A new option is added allowing you to ignore the chart pair and 
select what currencies you want to show news for, so that you do not have to display the news
for the chart pair.      

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 release 04-04-2012 to release 05-01-2012:
01 - Corrected errors in coding of prioritization of previous and current/future events. 
02 - Revised order of External Inputs.

Changes from release 05-01-2012 to release 05-25-2013: 
01 - Removes outdated .xml files (through previous year) from Experts files.
02 - Saves current files without the chart TF in the file name (reduces current files needed).
03 - Removes all reference to Broker Watermark, which new coding automatically handles.
04 - adds options for sub-window and right side of chart locations.
05 - adds option to not show the panel background.
06 - prefixes background boxes with "z" assuring "on top" display.

Changes from release 05-25-2013 to release 03-01-2014: 
01 - Only one .xml file is used as the source file for all charts with FFCal on them.
02 - Updating was 240 seconds while comment says minutes, now it is minutes.
03 - Checking currency pairs for a country with news now works on Symbols with broker prefix.
Note:  All these improvements have been contributed by "deVries".

Changes from release 03-01-2014 to release 03-17-2014: 
Contributed by "deVries".....
01 - Only one .xml file is used as the source file for all charts with FFCal on them.
02 - Updating was 240 seconds while comment says minutes, now it is minutes.
03 - Checking currency pairs for a country with news now works on Symbols with broker prefix.
04 - Deleted function for calculating GMT and replaced it with TimeGMT(), a new function inside 
     the new 600+ release.
05 - Totally changed the file reading and maintenance coding, involving numerous sections of
     coding, to streamline for compatibility with MT4 Build 600, and which results in faster
     exectution which is very noticeable when changing chart time frames.
Contributed by "qFish".....
06 - Improved the code controlling the timing of updates.     
Contributed by "atstrader".....
07 - Added option to ignore news for both sides of the pair and to replace with news for any pair
     or pairs featured.
                           
                                                                       - Traderathome, 03-17-2014       
                                                                         email: traderathome@msn.com                                                                                                                                     
---------------------------------------------------------------------------------------------------
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 
                                    
deVries   - for his excellent donated work that significantly altered and streamlined the file 
            handling coding to establish compatibility with the new release of MT4 Build 600+,
            and which has resulted in faster code execution.                                     
            (Jobs for deVries  www.mql5.com/en/job/new?prefered=deVries) 
qFish     - for his generously given time and help during the effort to improve this indicator.
atstrader - For a neat new option controlling for what pair/pairs(s) news is shown.
  
---------------------------------------------------------------------------------------------------
Suggested Colors:                    White Charts          Black Charts

FFCal_Title                          Black                 C'180,180,180'
News_Low_Impact                      Green                 C'046,186,046'
News_Medium_Impact                   MediumBlue            C'086,138,235'
News_High_Impact                     Crimson               C'217,000,000'
Bank_Holiday_Color                   DarkOrchid            Orchid
Remarks_Color                        DarkGray              DimGray      
Background_Color_                    White                 Black                                   

-------------------------------------------------------------------------------------------------*/
#property show_inputs
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1  CLR_NONE

#define READURL_BUFFER_SIZE   100

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

#import  "Wininet.dll"
int InternetOpenW(string,int,string,string,int);
int InternetConnectW(int,string,int,string,string,int,int,int);
int HttpOpenRequestW(int,string,string,int,string,int,string,int);
int InternetOpenUrlW(int,string,string,int,int,int);
int InternetReadFile(int,uchar  &arr[],int,int  &arr[]);
int InternetCloseHandle(int);
#import


extern int    BarPeriod=PERIOD_M1;
extern bool   ShowTable=True;
extern bool   ShowNewsLines=false;
extern bool   ShowEventFlags=true;
extern bool   NewsLineDescription=false;  //Object Description for NewsLines
extern bool   ShowCaution=true;
extern int    CautionCorner=0;
extern int    CautionXCoordinate=20;
extern int    CautionYCoordinate=10;
extern bool   ShowNextUp=true;
extern int    NextUpCorner=0;
extern int    NextUpXCoordinate=450;
extern int    NextUpYCoordinate=5;
extern bool   ShowLineText=false;
extern int    NewsLineTextSize=25;    // Number of Characters to use for News Line Text
extern int    NewsLineStyle=0;
extern int    NewsLineWidth=0;
extern bool   HistoryOn=True;
extern int    SleepInSeconds=10;

extern string Part_1                          = "Indicator Display Controls:";
extern bool   Indicator_On                    = true;
extern bool   Allow_Panel_In_Subwindow_1      = false;
extern bool   Allow_Panel_In_Subwindow_2      = false;
extern bool   Allow_Panel_At_Chart_Right      = false;
extern int    Display_Min_TF                  = 1;
extern int    Display_Max_TF                  = 240;
extern string TF_Choices                      = "1-5-15-30-60-240-1440-10080-43200";

extern string __                              = "";
extern string Part_2                          = "Headline Display Settings:";
extern color  FFCal_Title=Black;
extern color  Low_Impact_News_Color           = clrGold;
extern color  Medium_Impact_News_Color        = clrDarkOrange;
extern color  High_Impact_News_Color          = clrCrimson;
extern color  Bank_Holiday_Color              = clrSalmon;
extern bool   Bank_Holiday_On                 = false;
extern color  Remarks_Color                   = clrBlueViolet;
extern bool   Show_Panel_Background           = true;
extern color  Background_Color_               = clrWhite;
extern color  clrAlertOn                      = clrDarkGreen;
extern color  clrAlertOff                     = clrFireBrick;
extern int     Alert_Minutes_Before=0;    //Set to "0" for no Alert
extern bool   NotificationOn                  = False;
extern bool   AlertOn                         = False;
extern bool   MailOn                          = False;
extern int     Offset_Hours=0;     //Set to "0" to not adjust time/DST settings

// bool   Low_Impact_News_On              = true;
// bool   Medium_Impact_News_On           = true;

enum     type     { Not_Show           = 0
                  , All_News           = 1
                  , Low_and_higher     = 2
                  , Medium_and_higher  = 3
                  , High_Only          = 4
                  };
extern string ___                      = "";
extern string Part_3                   = "Other Currency News Settings:";
extern type     Show_USD_News          = All_News;
extern type     Show_EUR_News          = Low_and_higher;
extern type     Show_GBP_News          = Medium_and_higher;
extern type     Show_JPY_News          = Medium_and_higher;
extern type     Show_AUD_News          = High_Only;
extern type     Show_NZD_News          = High_Only;
extern type     Show_CAD_News          = High_Only;
extern type     Show_CHF_News          = High_Only;
extern type     Show_CNY_News          = High_Only;
extern bool     Ignore_Current_Symbol  = false;

//global buffers and variables---------------------------------------------------------------------
bool          Deinitialized,skip;
bool          FLAG_done0,FLAG_done1,FLAG_done2,FLAG_done3;
bool          FLAG_none0,FLAG_none1,FLAG_none2,FLAG_none3;
int           BankIdx1,cnr;
color         TxtColorNews;
datetime      newsTime,calendardate;   //sundaydate calendar
double        ExtMapBuffer0[];     // Contains (minutes until) each news event
int            xmlHandle,BoEvent,finalend,end,begin,minsTillNews,tmpMins,idxOfNext,
dispMinutes[9],newsIdx,next,nextNewsIdx,dispMins,Days,Hours,Mins;
int           dayStart,monthStart,F1,F2,i,j,k,curY,W,sx,sfx,Box,x1,x2,x3,y1,y2,y3,index;
int           WebUpdateFreq = 240; // 240 Minutes between web updates to not overload FF server
int           TxtSize       = 8;   //7
int           TitleSpacer   = 7;
int           EventSpacer   = 4;
int           curX          = 3;
static int     PrevMinute=-1;
string         xmlFileName;
string        xmlSearchName;
int           PrevTF=0;
static int     UpdateRateSec=10;

string        sUrl="http://www.forexfactory.com/ff_calendar_thisweek.xml"; //original
                                                                           //string        sUrl = "http://www.forexfactory.com/ffcal_week_this.xml";   // new 12Feb2015

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    = "z[FFCal] Box1";
string        box2    = "z[FFCal] Box2";
string        News1   = "z[FFCal] News1";
string        News2   = "z[FFCal] News2";
string        News3   = "z[FFCal] News3";
string        News4   = "z[FFCal] News4";
string        Sponsor = "z[FFCal] Sponsor";
bool     Default_selection  = false;
bool     Default_ray_left   = false;
bool     Default_ray_right  = false;
int   numM1Bars;

string tempstr;
//+-----------------------------------------------------------------------------------------------+
//| Indicator Initialization                                                                      |
//+-----------------------------------------------------------------------------------------------+
int init()
  {
//Get current time frame
   PrevTF=Period();
//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(Symbol()," ",Period(),", FFCal: Allow DLL Imports");
     }

//deVries: Management of FFCal.xml Files involves setting up a search to find and delete files
//that are not of this Sunday date.  This search is limited to 10 weeks back (604800 seconds). 
//Files with Sunday dates that are older will not be purged by this search and will have to be
//manually deleted by the user.
   xmlFileName=GetXmlFileName();
   for(k=calendardate;k>=calendardate-6048000;k=k-604800)
     {
      xmlSearchName=(StringConcatenate(TimeYear(k),"-",
                     PadString(DoubleToStr(TimeMonth(k),0),"0",2),"-",
                     PadString(DoubleToStr(TimeDay(k),0),"0",2),"-FFCal-News",".xml"));
      xmlHandle=FileOpen(xmlSearchName,FILE_BIN|FILE_READ);
      if(xmlHandle>=0) //file exists.  A return of -1 means file does not exist.
        {
         FileClose(xmlHandle);
         if(xmlSearchName!=xmlFileName)FileDelete(xmlSearchName);
        }
     }

   cnr=2; if(Allow_Panel_At_Chart_Right) {cnr=3;}
   if(Allow_Panel_In_Subwindow_1 && WindowsTotal( ) > 1){W= 1;}
   if(Allow_Panel_In_Subwindow_2 && WindowsTotal( ) > 2){W= 2;}
   else {W=0;}
////////////////////////////////////////////////////////////////////////
//W=0;                      // added//////////////////////////////////////
//if(WindowsTotal()>0) W=1; // added//////////////////////////////////////
/////////////////////////////////////////////////////////////////////// 
   SetIndexBuffer(0,ExtMapBuffer0);
   SetIndexStyle(0,DRAW_NONE);
   IndicatorShortName("FFCal");

   Deinitialized=false;

   return(0);
  }
//+-----------------------------------------------------------------------------------------------+
//| Indicator De-initialization                                                                   |
//+-----------------------------------------------------------------------------------------------+
int deinit()
  {

   FindDeleteObjectsA("LineNews"); /////////////         
   int obj_total=ObjectsTotal();
   for(i=obj_total; i>=0; i--) 
     {
      string name=ObjectName(i);
      if(StringSubstr(name,0,8)=="z[FFCal]") {ObjectDelete(name);}
     }
   ObjectDelete("AlertBefore");
   ObjectDelete("Alert");
   ObjectDelete("Notify");
   ObjectDelete("Mail");
   ObjectDelete("strNextUp");
   ObjectDelete("strCaution");
   for(i=1; i<=4; i++) ObjectDelete("Event"+DoubleToStr(i,0));
   return(0);
  }
//+-----------------------------------------------------------------------------------------------+
//| Indicator Start                                                                               |
//+-----------------------------------------------------------------------------------------------+  
int start()
  {

   if(checkNewBar(BarPeriod,true)!=true) return(0);
//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(!Deinitialized) {deinit(); Deinitialized=true;}
      //deleting old versions xml file 
      return(0);
     }

   InitNews(sUrl);

//qFish-----------------------------------------------------------------------------------------
//Perform remaining checks once per UpdateRateSec (Refreshing News from XML file)
   if(PrevTF==Period())
     {
      //if we haven't changed time frame then keep doing what we are doing
      if(MathMod(Seconds(),UpdateRateSec)==0)
        {
         return (true);
        }
      //otherwise, we've switched time frame and do not need to skip every 10 s,
      //thus immediately execute all of the start() function code   
      else
        {
         PrevTF=Period();
        }
     }

//Init the buffer array to zero just in case
   ArrayInitialize(ExtMapBuffer0,0);
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////	
//deVries---------------------------------------------------------------------------------------
//New xml file handling coding and revised parsing coding
   xmlHandle=FileOpen(xmlFileName,FILE_BIN|FILE_READ);
   if(xmlHandle>=0)
     {
      int size=FileSize(xmlHandle);
      sData=FileReadString(xmlHandle,size);
      FileClose(xmlHandle);
     }

//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
      
      type tp = Not_Show;
      if       (mainData[newsIdx][IMPACT] == "High")     { tp = High_Only; }
      else if  (mainData[newsIdx][IMPACT] == "Medium")   { tp = Medium_and_higher; }
      else if  (mainData[newsIdx][IMPACT] == "Low")      { tp = Low_and_higher; }
      else                                               { tp = All_News; }
      
      if( !IsNewsCurrency(mainData[newsIdx][COUNTRY], tp )) //deVries
        {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 (!StringSubstr(mainData[newsIdx][TITLE],0,4)== "Bank")
      else if((!Bank_Holiday_On) && (StringSubstr(mainData[newsIdx][TITLE],0,4)=="Bank"))
        {skip=true;}

      else if(!StringSubstr(mainData[newsIdx][TITLE],0,8)=="Daylight")
        {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=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, 
         //then 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 && numM1Bars!=iBars(Symbol(),PERIOD_M1))
           {

            if(AlertOn) Alert(Alert_Minutes_Before," minutes until news for "+mainData[newsIdx][COUNTRY],": ",mainData[newsIdx][TITLE]);
            if(NotificationOn) SendNotification(Alert_Minutes_Before+" minutes until news for "+mainData[newsIdx][COUNTRY]+": "+mainData[newsIdx][TITLE]);
            if(MailOn) SendMail(mainData[newsIdx][COUNTRY]+" "+Alert_Minutes_Before+" min News Alert",Alert_Minutes_Before+" minutes until news for "+mainData[newsIdx][COUNTRY]+": "+mainData[newsIdx][TITLE]);

            numM1Bars=iBars(Symbol(),PERIOD_M1);
           }

         //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

//----------------------------------------------------------------------------------------------
//Prioritization coding:  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 
      //most 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();

               Sleep(SleepInSeconds*1000);
               return (0);
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            //+-----------------------------------------------------------------------------------------------+
            //| Subroutines: recoded creation and maintenance of single xml file                              |
            //+-----------------------------------------------------------------------------------------------+   
            //deVries: void InitNews(string& mainData[][], string newsUrl)
            void InitNews(string newsUrl)
              {
               if(DoFileDownLoad()) //Added to check if the CSV file already exists
                 {
                  DownLoadWebPageToFile(newsUrl); //downloading the xml file
                 }
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            //deVries: If we have recent file don't download again
            bool DoFileDownLoad()
              {
               xmlHandle=0;
               int size;
               datetime time=TimeCurrent();
               //datetime time = TimeLocal();

               if(GlobalVariableCheck("Update.FF_Cal") == false)return(true);
               if((time - GlobalVariableGet("Update.FF_Cal")) > WebUpdateFreq*60)return(true);

               xmlFileName=GetXmlFileName();
               xmlHandle=FileOpen(xmlFileName,FILE_BIN|FILE_READ);  //check if file exist 
               if(xmlHandle>=0)//when the file exists we read data
                 {
                  size=FileSize(xmlHandle);
                  sData=FileReadString(xmlHandle,size);
                  FileClose(xmlHandle);//close it again check is done
                  return(false);//file exists no need to download again
                 }
               //File does not exist if FileOpen return -1 or if GetLastError = ERR_CANNOT_OPEN_FILE (4103)
               return(true); //commando true to download xml file     
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            //+-----------------------------------------------------------------------------------------------+
            //| Subroutine: getting the name of the ForexFactory .xml file                                    |
            //+-----------------------------------------------------------------------------------------------+ 
            //deVries: one file for all charts!   
            string GetXmlFileName()
              {
               int adjustDays=0;
               switch(TimeDayOfWeek(TimeLocal()))
                 {
                  case 0:
                     adjustDays=0;
                     break;
                  case 1:
                     adjustDays=1;
                     break;
                  case 2:
                     adjustDays=2;
                     break;
                  case 3:
                     adjustDays=3;
                     break;
                  case 4:
                     adjustDays=4;
                     break;
                  case 5:
                     adjustDays=5;
                     break;
                  case 6:
                     adjustDays=6;
                     break;
                 }
               calendardate=TimeLocal() -(adjustDays *86400);
               string fileName=(StringConcatenate(TimeYear(calendardate),"-",
                                PadString(DoubleToStr(TimeMonth(calendardate),0),"0",2),"-",
                                PadString(DoubleToStr(TimeDay(calendardate),0),"0",2),"-FFCal-News",".xml"));

               return(fileName); //Always a Sunday date  		
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            //+-----------------------------------------------------------------------------------------------+
            //| Subroutine: downloading the ForexFactory .xml file                                            |
            //+-----------------------------------------------------------------------------------------------+    
            //deVries: new coding replacing old "GrabWeb" coding
            void DownLoadWebPageToFile(string url="http://www.forexfactory.com/ff_calendar_thisweek.xml")
              {
               int HttpOpen=InternetOpenW(" ",0," "," ",0);
               int HttpConnect = InternetConnectW(HttpOpen, "", 80, "", "", 3, 0, 1);
               int HttpRequest = InternetOpenUrlW(HttpOpen, url, NULL, 0, 0, 0);

               int read[1];
               uchar  Buffer[];
               ArrayResize(Buffer,READURL_BUFFER_SIZE+1);
               string NEWS="";

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

               while(true)
                 {
                  InternetReadFile(HttpRequest,Buffer,READURL_BUFFER_SIZE,read);
                  string strThisRead = CharArrayToString(Buffer,0,read[0],CP_UTF8);
                  if(read[0]> 0)NEWS = NEWS + strThisRead;
                  else
                    {
                     FileWriteString(xmlHandle,NEWS);
                     FileClose(xmlHandle);
                     //Find the XML end tag to ensure a complete page was downloaded.
                     end=StringFind(NEWS,"</weeklyevents>",0);
                     //If the end of file tag is not found, a return -1 (or, "end <=0" in this case), 
                     //then return (false).
                     if(end==-1) {Alert(Symbol()," ",Period(),", FFCal Error: File download incomplete!");}
                     //Else, set global to time of last update
                     else {GlobalVariableSet("Update.FF_Cal",TimeCurrent());}
                     break;
                    }
                 }
               if(HttpRequest>0) InternetCloseHandle(HttpRequest);
               if(HttpConnect>0) InternetCloseHandle(HttpConnect);
               if(HttpOpen>0) InternetCloseHandle(HttpOpen);
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            //+-----------------------------------------------------------------------------------------------+
            //| Subroutine: to pad string                                                                     |
            //+-----------------------------------------------------------------------------------------------+ 
            //deVries: 
            string PadString(string toBePadded,string paddingChar,int paddingLength)
              {
               while(StringLen(toBePadded)<paddingLength)
                 {
                  toBePadded=StringConcatenate(paddingChar,toBePadded);
                 }
               return (toBePadded);
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            //+-----------------------------------------------------------------------------------------------+
            //| Subroutine: to ID currency even if broker has added a prefix to the symbol, and is used to    |
            //| determine the news to show, based on the users external inputs selections                     |
            //+-----------------------------------------------------------------------------------------------+  
            //deVries: works even when broker has attached prefix (or suffix) to the Currency, so that the
            //symbol format does not look like the standard example EURUSD or USDJPY.
            //atstrader: adds option to ignore the chart symbol pair and re-select other(s). 
            bool IsNewsCurrency(string fSymbol, type tt)
              {
               if(!Ignore_Current_Symbol && (StringFind(_Symbol,fSymbol,0)>=0)){return(true);}
               if(Show_USD_News <= tt && fSymbol == "USD"){return(true);}
               if(Show_GBP_News <= tt && fSymbol == "GBP"){return(true);}
               if(Show_EUR_News <= tt && fSymbol == "EUR"){return(true);}
               if(Show_CAD_News <= tt && fSymbol == "CAD"){return(true);}
               if(Show_AUD_News <= tt && fSymbol == "AUD"){return(true);}
               if(Show_CHF_News <= tt && fSymbol == "CHF"){return(true);}
               if(Show_JPY_News <= tt && fSymbol == "JPY"){return(true);}
               if(Show_NZD_News <= tt && fSymbol == "NZD"){return(true);}
               if(Show_CNY_News <= tt && fSymbol == "CNY"){return(true);}
               return(false);
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            //+-----------------------------------------------------------------------------------------------+
            //| Indicator Routine For Normal Display                                                          |
            //+-----------------------------------------------------------------------------------------------+  
            void OutputToChart()
              {
               string news4String,news3String,news2String,news1String;
               color  news4Color,news3Color,news2Color,news1Color;
               string strNextUpEvent="";
               color clrNextUp;

               //Print("0:",dispMinutes[0],"  1:",dispMinutes[1],"  2:",dispMinutes[2],"  3:",dispMinutes[3],"  4:",dispMinutes[4],"  5:",dispMinutes[5],"  6:",dispMinutes[6],"  7:",dispMinutes[7],"  8:",dispMinutes[8],"  9:",dispMinutes[9]);

               //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+"m ";}
               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+"h "+Mins+"m ";
                    }
                  else // days, hours, and minutes
                    {
                     Days = MathRound(Hours / 24);
                     Hours = Hours % 24;
                     TimeStr=Days+" days "+Hours+"h "+Mins+"m ";
                    }
                 }
               index=StringFind(TimeStr+sinceUntil+dispCountry[3],"since  m",0);
               TxtColorNews=ImpactToColor(dispImpact[3]);
               ObjectDelete(News4);
               ObjectCreate(News4,OBJ_LABEL,W,0,0);
               if((index!=-1) || (FLAG_none3))
                 {
                  news4String="";
                  news4Color=clrNONE;
                  ObjectSetText(News4," ",
                                TxtSize,Text_Style,Remarks_Color);
                  event[4]=" ";
                 }
               else
                 {
                  news4String=" "+dispCountry[3]+": "+dispTitle[3]+"  ";////////////////////////////////////
                  news4String=StringSubstr(news4String,0,NewsLineTextSize);
                  news4Color=TxtColorNews;
                  ObjectSetText(News4,TimeStr+sinceUntil+dispCountry[3]+": "+dispTitle[3],TxtSize,Text_Style,TxtColorNews);
                  event[4]=TimeStr+sinceUntil+dispCountry[3]+": "+dispTitle[3];
                  if(dispMinutes[3]>0) {strNextUpEvent=event[4];clrNextUp=TxtColorNews;}
                 }
                 
               

               //Compose third event description line--------------------------------------------------------- 	           
               sinceUntil="until ";
               dispMins=dispMinutes[2]+1;
               if(dispMinutes[2]<=0) {dispMins=dispMins-1; sinceUntil="since "; dispMins*=-1;}
               //if (dispMinutes[2]) intNextUpEvent=3;
               if(dispMins<60) {TimeStr=dispMins+"m ";}
               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+"h "+Mins+"m ";
                    }
                  else // days, hours, and minutes
                    {
                     Days = MathRound(Hours / 24);
                     Hours = Hours % 24;
                     TimeStr=Days+" days "+Hours+"h "+Mins+"m ";
                    }
                 }
               index=StringFind(TimeStr+sinceUntil+dispCountry[2],"since  m",0);
               TxtColorNews=ImpactToColor(dispImpact[2]);
               ObjectDelete(News3);
               ObjectCreate(News3,OBJ_LABEL,W,0,0);
               if((index!=-1) || (FLAG_none2))
                 {
                  news3String="";
                  news3Color=clrNONE;
                  ObjectSetText(News3," ",
                                TxtSize,Text_Style,Remarks_Color);
                  event[3]=" ";
                 }
               else
                 {
                  news3String=" "+dispCountry[2]+": "+dispTitle[2]+"  ";////////////////////////////////////
                  news3String=StringSubstr(news3String,0,NewsLineTextSize);
                  news3Color=TxtColorNews;
                  ObjectSetText(News3,TimeStr+sinceUntil+dispCountry[2]+": "+dispTitle[2],TxtSize,Text_Style,TxtColorNews);
                  event[3]=TimeStr+sinceUntil+dispCountry[2]+": "+dispTitle[2];
                  if(dispMinutes[2]>0) {strNextUpEvent=event[3];clrNextUp=TxtColorNews;}
                 }

               //Compose second event description line-------------------------------------------------------- 	           
               sinceUntil="until ";
               dispMins=dispMinutes[1]+1;
               if(dispMinutes[1]<=0) {dispMins=dispMins-1; sinceUntil="since "; dispMins*=-1;}
               //if (dispMins > 0) intNextUpEvent=2;
               if(dispMins<60) {TimeStr=dispMins+"m ";}
               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+"h "+Mins+"m ";
                    }
                  else // days, hours, and minutes
                    {
                     Days=MathRound(Hours/24);
                     Hours=Hours%24;
                     TimeStr=Days+" days "+Hours+"h "+Mins+"m ";
                    }
                 }
               index=StringFind(TimeStr+sinceUntil+dispCountry[1],"since  m",0);
               TxtColorNews=ImpactToColor(dispImpact[1]);
               ObjectDelete(News2);
               ObjectCreate(News2,OBJ_LABEL,W,0,0);
               if((index!=-1) || (FLAG_none1))
                 {
                  news2String="";
                  news2Color=clrNONE;
                  ObjectSetText(News2," ",
                                TxtSize,Text_Style,Remarks_Color);
                  event[2]=" ";
                 }
               else
                 {
                  news2String=" "+dispCountry[1]+": "+dispTitle[1]+"  ";////////////////////////////////////	      
                  news2String=StringSubstr(news2String,0,NewsLineTextSize);
                  news2Color=TxtColorNews;
                  ObjectSetText(News2,TimeStr+sinceUntil+dispCountry[1]+": "+dispTitle[1],TxtSize,Text_Style,TxtColorNews);
                  event[2]=TimeStr+sinceUntil+dispCountry[1]+": "+dispTitle[1];
                  if(dispMinutes[1]>0) {strNextUpEvent=event[2];clrNextUp=TxtColorNews;}
                 }

               //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 > 0) intNextUpEvent=1;
               if(dispMins<60) {TimeStr=dispMins+"m ";}
               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+"h "+Mins+"m ";
                    }
                  else  // days, hours, and minutes
                    {
                     Days=MathRound(Hours/24);
                     Hours=Hours%24;
                     TimeStr=Days+" days "+Hours+"h "+Mins+"m ";
                    }
                 }
               index=StringFind(TimeStr+sinceUntil+dispCountry[0],"since  m",0); //Comment (index);	
               TxtColorNews=ImpactToColor(dispImpact[0]);
               ObjectDelete(News1);
               ObjectCreate(News1,OBJ_LABEL,W,0,0);
               if((index!=-1) || (FLAG_none0))
                 {
                  news1String="";
                  news1Color=clrNONE;
                  ObjectSetText(News1," ",TxtSize,Text_Style,Remarks_Color);
                  event[1]=" ";
                 }
               else
                 {
                  //Print("***  ",dispCountry[0] + ": " + dispTitle[0]); ////////////////////////////////////////////////////////////////
                  //news1String=TimeStr + sinceUntil + dispCountry[0] + ": " + dispTitle[0];////////////////////////////////////
                  news1String=" "+dispCountry[0]+": "+dispTitle[0]+"  ";////////////////////////////////////
                  news1String=StringSubstr(news1String,0,NewsLineTextSize);
                  news1Color=TxtColorNews;
                  ObjectSetText(News1,TimeStr+sinceUntil+dispCountry[0]+": "+dispTitle[0],TxtSize,Text_Style,TxtColorNews);
                  event[1]=TimeStr+sinceUntil+dispCountry[0]+": "+dispTitle[0];
                  if(dispMinutes[0]>0) {strNextUpEvent=event[1];clrNextUp=TxtColorNews;}
                 }
               ObjectDelete("strNextUp");
               if(ShowNextUp && strNextUpEvent!="")
                 {
                  ObjectCreate("strNextUp",OBJ_LABEL,0,0,0);
                  ObjectSetText("strNextUp",strNextUpEvent,TxtSize+4,"Arial Balck",clrNextUp);
                  ObjectSet("strNextUp",OBJPROP_CORNER,NextUpCorner);
                  ObjectSet("strNextUp",OBJPROP_XDISTANCE,NextUpXCoordinate);
                  ObjectSet("strNextUp",OBJPROP_YDISTANCE,NextUpYCoordinate);
                  ObjectSet("strNextUp",OBJPROP_SELECTABLE,0);
                 }
               
               ObjectDelete("strCaution");
               if(ShowCaution && strCaution()!="")
                  {
                  ObjectCreate("strCaution",OBJ_LABEL,0,0,0);
                  ObjectSetText("strCaution",strCaution(),12,"Arial Black",clrRed);
                  ObjectSet("strCaution",OBJPROP_CORNER,CautionCorner);
                  ObjectSet("strCaution",OBJPROP_XDISTANCE,CautionXCoordinate);
                  ObjectSet("strCaution",OBJPROP_YDISTANCE,CautionYCoordinate);
                  ObjectSet("strCaution",OBJPROP_SELECTABLE,0);
                  
                  }
               //Do background---------------------------------------------------------------------------------
               //Set variables.   
               x1 = 0;
               x2 = 0;
               y2 = 1;

               //Automate Determination of Width of Background
               //Determine the length (x1) of the maximum length event string (i = 1-4)
               for(i=1; i<=4; i++)
                 {
                  if(i==0) {x1=StringLen(event[i]);}
                  else
                    {
                     if(StringLen(event[i])>x1)
                       {
                        x1=StringLen(event[i]);
                       }
                    }
                 }
               if(x1<94) {x2=95;}
               else {x2=x1-94+95;}//x2 = starts where x1 characters stop

                                  //Set up for background boxes             
               //Space in Panel is req'd for Watermark if no subwindow exists and the panel is in the
               //main window on the left side, or if a subwindow does exist and the panel is in the
               //subwindow on the left side.
               if((!Allow_Panel_At_Chart_Right) && 
                  (WindowsTotal()==1 || (WindowsTotal()>1 && Allow_Panel_In_Subwindow_1)))
                 {
                  //Use larger rectangle Panel & start text higher from bottom
                  curY =18;
                  Box=64;//64
                  G="gg";
                  //block size "gg" requires background #2 to start further right
                  x2=x2+46;
                 }
               //No space in Panel is req'd for Watermark if a subwindow exists and the panel is in the
               //main window, or if the panel is in the subwindow, but on the right side.          
               else
                 {
                  //Use shorter rectangle Panel & start text lower from bottom  
                  curY =6;
                  Box=54;//54
                  G="ggg";
                 }


               datetime timeSeconds1p,timeSeconds2p,timeSeconds3p,timeSeconds4p;
               datetime timeSeconds1=TimeCurrent()+dispMinutes[0]*60; timeSeconds1p=timeSeconds1; if(dispMinutes[0]>-1)timeSeconds1p=timeSeconds1p+Period()*60;
               datetime timeSeconds2=TimeCurrent()+dispMinutes[1]*60; timeSeconds2p=timeSeconds2; if(dispMinutes[1]>-1)timeSeconds2p=timeSeconds2p+Period()*60;
               datetime timeSeconds3=TimeCurrent()+dispMinutes[2]*60; timeSeconds3p=timeSeconds3; if(dispMinutes[2]>-1)timeSeconds3p=timeSeconds3p+Period()*60;
               datetime timeSeconds4=TimeCurrent()+dispMinutes[3]*60; timeSeconds4p=timeSeconds4; if(dispMinutes[3]>-1)timeSeconds4p=timeSeconds4p+Period()*60;
               double lineHigh1,lineLow1,lineHigh2,lineLow2,lineHigh3,lineLow3,lineHigh4,lineLow4;
               int linePips=5;                               // chane TimeCurrent()  to iTime(Symbol(),1,0)
               lineHigh1=(iHigh(Symbol(),PERIOD_D1,0)+iLow(Symbol(),PERIOD_D1,0))/2+PipsToPrice(linePips);if(dispMinutes[0]<=0) lineHigh1=High[iBarShift(Symbol(),0,timeSeconds1)];
               lineLow1=(iHigh(Symbol(),PERIOD_D1,0)+iLow(Symbol(),PERIOD_D1,0))/2-PipsToPrice(linePips);if(dispMinutes[0]<=0) lineLow1=Low[iBarShift(Symbol(),0,timeSeconds1)];
               lineHigh2=(iHigh(Symbol(),PERIOD_D1,0)+iLow(Symbol(),PERIOD_D1,0))/2+PipsToPrice(linePips);if(dispMinutes[1]<=0) lineHigh2=High[iBarShift(Symbol(),0,timeSeconds2)];
               lineLow2=(iHigh(Symbol(),PERIOD_D1,0)+iLow(Symbol(),PERIOD_D1,0))/2-PipsToPrice(linePips);if(dispMinutes[1]<=0) lineLow2=Low[iBarShift(Symbol(),0,timeSeconds2)];
               lineHigh3=(iHigh(Symbol(),PERIOD_D1,0)+iLow(Symbol(),PERIOD_D1,0))/2+PipsToPrice(linePips);if(dispMinutes[2]<=0) lineHigh3=High[iBarShift(Symbol(),0,timeSeconds3)];
               lineLow3=(iHigh(Symbol(),PERIOD_D1,0)+iLow(Symbol(),PERIOD_D1,0))/2-PipsToPrice(linePips);if(dispMinutes[2]<=0) lineLow3=Low[iBarShift(Symbol(),0,timeSeconds3)];
               lineHigh4=(iHigh(Symbol(),PERIOD_D1,0)+iLow(Symbol(),PERIOD_D1,0))/2+PipsToPrice(linePips);if(dispMinutes[3]<=0) lineHigh4=High[iBarShift(Symbol(),0,timeSeconds4)];
               lineLow4=(iHigh(Symbol(),PERIOD_D1,0)+iLow(Symbol(),PERIOD_D1,0))/2-PipsToPrice(linePips);if(dispMinutes[3]<=0) lineLow4=Low[iBarShift(Symbol(),0,timeSeconds4)];
               ObjectDelete(0,"LineNews1");ObjectDelete(0,"LineNews2"); ObjectDelete(0,"LineNews3");  ObjectDelete(0,"LineNews4");
               
               if(ShowNewsLines==true)
                 {

                  //  If Multiple Events at same time then add spacing
                  tempstr="";
                  if(timeSeconds1p==timeSeconds2p)
                    {
                     StringInit(tempstr,StringLen(news1String)," ");
                     news2String=tempstr+news2String;
                    }
                  if(timeSeconds2p==timeSeconds3p)
                    {
                     StringInit(tempstr,StringLen(news2String)," ");
                     news3String=tempstr+news3String;
                    }
                  if(timeSeconds3p==timeSeconds4p)
                    {
                     StringInit(tempstr,StringLen(news3String)," ");
                     news4String=tempstr+news4String;
                    }

                  if(TimeCurrent()<=timeSeconds1p || HistoryOn) 
                    {
                     SetTLine(0,"LineNews1",0,timeSeconds1p,lineHigh1,timeSeconds1p,lineLow1,news1Color,NewsLineStyle,NewsLineWidth);   //  +Period()*60
                                                                                                                                        //ObjectSetText("LineNews1",news1String+" "+DateStringA(timeSeconds1+60,0));     
                     if(NewsLineDescription) ObjectSetText("LineNews1",news1String);
                    }
                  //if(dispMinutes[1]<=0) news2Color=clrNONE ;
                  if(TimeCurrent()<=timeSeconds2p || HistoryOn) 
                    {
                     SetTLine(0,"LineNews2",0,timeSeconds2p,lineHigh2,timeSeconds2p,lineLow2,news2Color,NewsLineStyle,NewsLineWidth);
                     //ObjectSetText("LineNews2",news2String+" "+DateStringA(timeSeconds2+60,0));    
                     if(NewsLineDescription) ObjectSetText("LineNews2",news2String);
                    }
                  //if(dispMinutes[2]<=0) news3Color=clrNONE ;
                  if(TimeCurrent()<=timeSeconds3p || HistoryOn) 
                    {
                     SetTLine(0,"LineNews3",0,timeSeconds3p,lineHigh3,timeSeconds3p,lineLow3,news3Color,NewsLineStyle,NewsLineWidth);
                     //ObjectSetText("LineNews3",news3String+" "+DateStringA(timeSeconds3+60,0));  
                     if(NewsLineDescription) ObjectSetText("LineNews3",news3String);
                    }
                  //if(dispMinutes[3]<=0) news4Color=clrNONE ;
                  if(TimeCurrent()<=timeSeconds4p || HistoryOn)
                    {
                     SetTLine(0,"LineNews4",0,timeSeconds4p,lineHigh4,timeSeconds4p,lineLow4,news4Color,NewsLineStyle,NewsLineWidth);
                     //ObjectSetText("LineNews4",news4String+" "+DateStringA(timeSeconds4+60,0));    
                     if(NewsLineDescription) ObjectSetText("LineNews4",news4String);    
                    }
                 }
               if(ShowEventFlags==true)
                 {

                  //  If Multiple Events at same time then add spacing
                  tempstr="";
                  
                  if(TimeCurrent()<=timeSeconds1p || HistoryOn) 
                    if (news1String!="")
                    {
                    if (HistoryOn) tempstr=news1String+" "+timeSeconds1p; else tempstr="Event1";
                     EventCreate(ChartID(),tempstr,0,news1String,timeSeconds1p,news1Color,20,True, False,False,0);  
                     ObjectSet(tempstr,OBJPROP_TOOLTIP,tempstr);                                                         
                     ObjectSetInteger(NULL,tempstr,OBJPROP_TIMEFRAMES,OBJ_PERIOD_M1|OBJ_PERIOD_M5|OBJ_PERIOD_M15|OBJ_PERIOD_M30|OBJ_PERIOD_H1|OBJ_PERIOD_H4);
                    }
                  //if(dispMinutes[1]<=0) news2Color=clrNONE ;
                  if(TimeCurrent()<=timeSeconds2p || HistoryOn) 
                    if (news2String!="")
                    {
                    if (HistoryOn) tempstr=news2String+" "+timeSeconds2p; else tempstr="Event2";
                     EventCreate(ChartID(),tempstr,0,news2String,timeSeconds2p,news2Color,20,True, False,False,0);  
                     ObjectSet(tempstr,OBJPROP_TOOLTIP,tempstr);
                     ObjectSetInteger(NULL,tempstr,OBJPROP_TIMEFRAMES,OBJ_PERIOD_M1|OBJ_PERIOD_M5|OBJ_PERIOD_M15|OBJ_PERIOD_M30|OBJ_PERIOD_H1|OBJ_PERIOD_H4);
                    }
                  //if(dispMinutes[2]<=0) news3Color=clrNONE ;
                  if(TimeCurrent()<=timeSeconds3p || HistoryOn) 
                    if (news3String!="") 
                    {
                    if (HistoryOn) tempstr=news3String+" "+timeSeconds3p; else tempstr="Event3";
                     EventCreate(ChartID(),tempstr,0,news3String,timeSeconds3p,news3Color,20,True, False,False,0);  
                     ObjectSet(tempstr,OBJPROP_TOOLTIP,tempstr);
                     ObjectSetInteger(NULL,tempstr,OBJPROP_TIMEFRAMES,OBJ_PERIOD_M1|OBJ_PERIOD_M5|OBJ_PERIOD_M15|OBJ_PERIOD_M30|OBJ_PERIOD_H1|OBJ_PERIOD_H4);
                    }
                  //if(dispMinutes[3]<=0) news4Color=clrNONE ;
                  if(TimeCurrent()<=timeSeconds4p || HistoryOn)
                    if (news4String!="")
                    {
                    if (HistoryOn) tempstr=news4String+" "+timeSeconds4p; else tempstr="Event4";
                     EventCreate(ChartID(),tempstr,0,news4String,timeSeconds4p,news4Color,20,True, False,False,0);   
                     ObjectSet(tempstr,OBJPROP_TOOLTIP,tempstr);
                     ObjectSetInteger(NULL,tempstr,OBJPROP_TIMEFRAMES,OBJ_PERIOD_M1|OBJ_PERIOD_M5|OBJ_PERIOD_M15|OBJ_PERIOD_M30|OBJ_PERIOD_H1|OBJ_PERIOD_H4);
                    }
                 }
               if(ShowLineText==true)
                 {
                  ObjectDelete(0,"LineNews1text");
                  if(TimeCurrent()<=timeSeconds1p || HistoryOn) SetText(0,"LineNews1text",0,timeSeconds1p,lineHigh1,news1String,"Arial",7,news1Color);
                  ObjectSetInteger(0,"LineNews1text",OBJPROP_ANCHOR,ANCHOR_LEFT); ObjectSetDouble(0,"LineNews1text",OBJPROP_ANGLE,90);
                  ObjectDelete(0,"LineNews2text");
                  if(TimeCurrent()<=timeSeconds2p || HistoryOn) SetText(0,"LineNews2text",0,timeSeconds2p,lineLow2,news2String,"Arial",7,news2Color);
                  ObjectSetInteger(0,"LineNews2text",OBJPROP_ANCHOR,ANCHOR_RIGHT); ObjectSetDouble(0,"LineNews2text",OBJPROP_ANGLE,90);
                  ObjectDelete(0,"LineNews3text");
                  if(TimeCurrent()<=timeSeconds3p || HistoryOn) SetText(0,"LineNews3text",0,timeSeconds3p,lineHigh3,news3String,"Arial",7,news3Color);
                  ObjectSetInteger(0,"LineNews3text",OBJPROP_ANCHOR,ANCHOR_LEFT); ObjectSetDouble(0,"LineNews3text",OBJPROP_ANGLE,90);
                  ObjectDelete(0,"LineNews4text");
                  if(TimeCurrent()<=timeSeconds4p || HistoryOn) SetText(0,"LineNews4text",0,timeSeconds4p,lineLow4,news4String,"Arial",7,news4Color);
                  ObjectSetInteger(0,"LineNews4text",OBJPROP_ANCHOR,ANCHOR_RIGHT); ObjectSetDouble(0,"LineNews4text",OBJPROP_ANGLE,90);
                 }

               //Draws Background boxes
               if(Show_Panel_Background && ShowTable==true) 
                 {
                  ObjectCreate(box1,OBJ_LABEL,W,0,0);
                  ObjectSetText(box1,G,Box,"Webdings");
                  ObjectSet(box1,OBJPROP_CORNER,cnr);
                  ObjectSet(box1,OBJPROP_XDISTANCE,1);
                  ObjectSet(box1,OBJPROP_YDISTANCE,1);
                  ObjectSet(box1,OBJPROP_BGCOLOR,Background_Color_);
                  ObjectSet(box1,OBJPROP_BACK,true);

                  ObjectCreate(box2,OBJ_LABEL,W,0,0);
                  ObjectSetText(box2,G,Box,"Webdings");
                  ObjectSet(box2,OBJPROP_CORNER,cnr);
                  ObjectSet(box2,OBJPROP_XDISTANCE,x2);
                  ObjectSet(box2,OBJPROP_YDISTANCE,1);
                  ObjectSet(box2,OBJPROP_BGCOLOR,Background_Color_);
                  ObjectSet(box2,OBJPROP_BACK,true); 
                 }

               int curXnew=curX;
               if(ShowTable!=true) {curXnew=-1000;}//////////////////////////////////////
                                                   //Draw Event4
               ObjectSet(News4,OBJPROP_CORNER,cnr);
               ObjectSet(News4,OBJPROP_XDISTANCE,curXnew);
               ObjectSet(News4,OBJPROP_YDISTANCE,curY);
               curY=curY+TxtSize+EventSpacer;

               //Draw Event3
               ObjectSet(News3,OBJPROP_CORNER,cnr);
               ObjectSet(News3,OBJPROP_XDISTANCE,curXnew);
               ObjectSet(News3,OBJPROP_YDISTANCE,curY);
               curY=curY+TxtSize+EventSpacer;

               //Draw Event2
               ObjectSet(News2,OBJPROP_CORNER,cnr);
               ObjectSet(News2,OBJPROP_XDISTANCE,curXnew);
               ObjectSet(News2,OBJPROP_YDISTANCE,curY);
               curY=curY+TxtSize+EventSpacer;

               //Draw Event1   
               ObjectSet(News1,OBJPROP_CORNER,cnr); //Print("********************   ",News1);
               ObjectSet(News1,OBJPROP_XDISTANCE,curXnew);
               ObjectSet(News1,OBJPROP_YDISTANCE,curY);
               curY=curY+TxtSize+TitleSpacer;

               //Finish with title-----------------------------------------------------------------------------
               ObjectDelete(Sponsor);
               ObjectCreate(Sponsor,OBJ_LABEL,W,0,0);
               ObjectSetText(Sponsor,"FFCAL News:",TxtSize,"Verdana",FFCal_Title);
               ObjectSet(Sponsor,OBJPROP_CORNER,cnr);
               ObjectSet(Sponsor,OBJPROP_XDISTANCE,curXnew);
               ObjectSet(Sponsor,OBJPROP_YDISTANCE,curY);

               // Notfiication Bar
               if(Alert_Minutes_Before!=0)
                 {
                  string strObjName;

                  strObjName="AlertBefore";
                  ObjectDelete(strObjName);
                  ObjectCreate(strObjName,OBJ_LABEL,W,0,0);
                  ObjectSetText(strObjName,Alert_Minutes_Before+" min",TxtSize,"Verdana",clrAlertOn);
                  ObjectSet(strObjName,OBJPROP_CORNER,cnr);
                  ObjectSet(strObjName,OBJPROP_XDISTANCE,curXnew+100);
                  ObjectSet(strObjName,OBJPROP_YDISTANCE,curY);

                  strObjName="Alert";
                  ObjectDelete(strObjName);
                  ObjectCreate(strObjName,OBJ_LABEL,W,0,0);
                  if(AlertOn) ObjectSetText(strObjName,"Alert",TxtSize,"Verdana",clrAlertOn);
                  else ObjectSetText(strObjName,"Alert",TxtSize,"Verdana",clrAlertOff);
                  ObjectSet(strObjName,OBJPROP_CORNER,cnr);
                  ObjectSet(strObjName,OBJPROP_XDISTANCE,curXnew+150);
                  ObjectSet(strObjName,OBJPROP_YDISTANCE,curY);

                  strObjName="Notify";
                  ObjectDelete(strObjName);
                  ObjectCreate(strObjName,OBJ_LABEL,W,0,0);
                  if(NotificationOn) ObjectSetText(strObjName,"Notify",TxtSize,"Verdana",clrAlertOn);
                  else ObjectSetText(strObjName,"Notify",TxtSize,"Verdana",clrAlertOff);
                  ObjectSet(strObjName,OBJPROP_CORNER,cnr);
                  ObjectSet(strObjName,OBJPROP_XDISTANCE,curXnew+200);
                  ObjectSet(strObjName,OBJPROP_YDISTANCE,curY);

                  strObjName="Mail";
                  ObjectDelete(strObjName);
                  ObjectCreate(strObjName,OBJ_LABEL,W,0,0);
                  if(MailOn) ObjectSetText(strObjName,"Mail",TxtSize,"Verdana",clrAlertOn);
                  else ObjectSetText(strObjName,"Mail",TxtSize,"Verdana",clrAlertOff);
                  ObjectSet(strObjName,OBJPROP_CORNER,cnr);
                  ObjectSet(strObjName,OBJPROP_XDISTANCE,curXnew+250);
                  ObjectSet(strObjName,OBJPROP_YDISTANCE,curY);

                 }
               else
                 {
                  ObjectDelete("AlertBefore");
                  ObjectDelete("Alert");
                  ObjectDelete("Notif");
                  ObjectDelete("Mail");
                 }

              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            //+-----------------------------------------------------------------------------------------------+
            //| 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    changed by deVries                                      |
            //+-----------------------------------------------------------------------------------------------+ 
            datetime MakeDateTime(string strDate,string strTime) //not string now datetime
              {
               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;}

               datetime newsevent=StringToTime(strYear+"."+strMonth+"."+
                                               strDay)+nHour24*3600+(StringToInteger(strMinute)*60);
               return(newsevent);
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            //SetTLine(0,name,0,time1,price1,time2,price2,clr, style, width);
            bool SetTLine(   const long            chart_ID=0,        // chart's ID
                          const string          name="TrendLine",  // line name
                          const int             sub_window=0,      // subwindow index
                          datetime              time1=0,           // first point time
                          double                price1=0,          // first point price
                          datetime              time2=0,           // second point time
                          double                price2=0,          // second point price
                          const color           clr=clrRed,        // line color
                          const int             style=0,// line style
                          const int             width=2,           // line width
                          const bool            back=false,        // in the background
                          const bool            selection=true,    // highlight to move
                          const bool            ray_left=false,    // line's continuation to the left
                          const bool            ray_right=true,// line's continuation to the right
                          const bool            hidden=false,// hidden in the object list
                          const long            z_order=0) // priority for mouse click
              {
               ResetLastError();
               if(time2==0 || time1==0 || price2==0 || price1==0) return(0); /////////////////////
               if(!ObjectCreate(chart_ID,name,OBJ_TREND,sub_window,time1,price1,time2,price2))
                 {
                  //     Print(__FUNCTION__," ->",name," ",
                  //          ": failed to create a trend line! Error code = ",GetLastError());
                  return(false);
                 }
               ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
               ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
               ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
               ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
               ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,Default_selection);
               ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,Default_selection);
               ObjectSetInteger(chart_ID,name,OBJPROP_RAY_LEFT,Default_ray_left);
               ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,Default_ray_right);
               ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
               ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
               return(true);
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            //SetText(0,name,0,TimeCurrent(),price,text)  
            bool SetText(const long                 chart_ID=0,               // chart's ID
                         const string            name="Text",              // object name
                         const int               sub_window=0,             // subwindow index
                         datetime                time=0,                   // anchor point time
                         double                  price=0,                  // anchor point price
                         const string            text="Text",              // the text itself
                         const string            font="Arial",             // font
                         const int               font_size=7,// font size
                         const color             clr=Red,// color
                         const double            angle=00.0,// text slope
                         const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT,// anchor type
                         const bool              back=false,               // in the background
                         const bool              selection=false,          // highlight to move
                         const bool              hidden=true,              // hidden in the object list
                         const long              z_order=0)                // priority for mouse click
              {
               ResetLastError();
               if(!ObjectCreate(chart_ID,name,OBJ_TEXT,sub_window,time,price))
                 {
                  //  Print(__FUNCTION__,"  name->",name,
                  //        ": failed to create \"Text\" object! Error code = ",GetLastError());
                  return(false);
                 }
               ObjectCreate(chart_ID,name,OBJ_TEXT,sub_window,time,price);/////////
               ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
               ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
               ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
               ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
               ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
               ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
               ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
               ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,Default_selection);
               ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,Default_selection);  //difference?
               ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
               ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
               return(true);
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            string DateStringA(datetime timeX,int dateType=1)
              {
               string dateString;
               string hours;
               string minutes;
               string seconds;
               string dayNumber;
               string dayName;
               string dayNumberMonth30;
               string dayNumberMonth12;
               string monthName;
               hours    =IntegerToString(TimeHour(timeX));       if(StringLen(hours)==1)     hours     ="0"+hours;
               minutes  =IntegerToString(TimeMinute(timeX));     if(StringLen(minutes)==1)   minutes   ="0"+minutes;
               seconds  =IntegerToString(TimeSeconds(timeX));    if(StringLen(seconds)==1)   seconds   ="0"+seconds;
               dayNumber=IntegerToString(TimeDay(timeX));        if(StringLen(dayNumber)==1) dayNumber ="0"+dayNumber;

               dayNumberMonth30=IntegerToString(TimeDay(timeX));  if(StringLen(dayNumberMonth30)==1) dayNumberMonth30 ="0"+dayNumberMonth30;
               dayNumberMonth12=IntegerToString(TimeMonth(timeX)); if(StringLen(dayNumberMonth12)==1) dayNumberMonth12 ="0"+dayNumberMonth12;

               if(TimeDayOfWeek(timeX)==0) dayName=("Sun");
               else if(TimeDayOfWeek(timeX) == 1) dayName = ("Mon");
               else if(TimeDayOfWeek(timeX) == 2) dayName = ("Tue");
               else if(TimeDayOfWeek(timeX) == 3) dayName = ("Wed");
               else if(TimeDayOfWeek(timeX) == 4) dayName = ("Thr");
               else if(TimeDayOfWeek(timeX) == 5) dayName = ("Fri");
               else if(TimeDayOfWeek(timeX) == 6) dayName = ("Sat");
               else  return ("DayOfWeekError");
               if(TimeMonth(timeX)==1) monthName=("Jan");
               else if(TimeMonth(timeX) == 2)  monthName = ("Feb");
               else if(TimeMonth(timeX) == 3)  monthName = ("Mar");
               else if(TimeMonth(timeX) == 4)  monthName = ("Apr");
               else if(TimeMonth(timeX) == 5)  monthName = ("May");
               else if(TimeMonth(timeX) == 6)  monthName = ("Jun");
               else if(TimeMonth(timeX) == 7)  monthName = ("Jul");
               else if(TimeMonth(timeX) == 8)  monthName = ("Aug");
               else if(TimeMonth(timeX) == 9)  monthName = ("Sep");
               else if(TimeMonth(timeX) == 10) monthName = ("Oct");
               else if(TimeMonth(timeX) == 11) monthName = ("Nov");
               else if(TimeMonth(timeX) == 12) monthName = ("Dec");
               else  return ("TimeMonthError");
               if(dateType==0) // 2014.06.02 10:52
                 {
                  dateString=IntegerToString(TimeYear(timeX))+"."+dayNumberMonth12+"."+dayNumberMonth30+" "+hours+":"+minutes;
                 }
               else if(dateType==1) // Thur2014.06.02_10:52
                 {
                  dateString=dayName+""+IntegerToString(TimeYear(timeX))+"."+dayNumberMonth12+"."+dayNumberMonth30+"_"+hours+":"+minutes;
                 }
               else if(dateType==2) // Thur2014Jun02 10:52
                 {
                  dateString=dayName+""+IntegerToString(TimeYear(timeX))+""+monthName+""+dayNumberMonth30+"_"+hours+":"+minutes;
                 }
               else if(dateType==3) // Thr10:52_02Jun2014
                 {
                  dateString=dayName+""+hours+":"+minutes+"_"+dayNumber+""+monthName+""+IntegerToString(TimeYear(timeX));
                 }
               else if(dateType==4) // 02Jun2014
                 {
                  dateString=hours=dayNumber+""+monthName+""+IntegerToString(TimeYear(timeX));
                 }
               else if(dateType==5) // 10:52_Thr02Jun2014
                 {
                  dateString=hours+":"+minutes+"_"+dayName+""+dayNumber+""+monthName+""+IntegerToString(TimeYear(timeX));
                 }
               else if(dateType==6) // 2014.06.02
                 {
                  dateString=IntegerToString(TimeYear(timeX))+"."+dayNumberMonth12+"."+dayNumberMonth30;
                 }
               else if(dateType==7) // 10:52_02Jun2014
                 {
                  dateString=hours+":"+minutes+"_"+dayNumber+""+monthName+""+IntegerToString(TimeYear(timeX));
                 }
               else if(dateType==8) // 10:52
                 {
                  dateString=hours+":"+minutes;
                 }
               else if(dateType==9) // Thr10:52  1401706320
                 {
                  dateString=dayName+hours+":"+minutes;
                 }
               else if(dateType==10) // 1401706320 //seconds from 01 Jan 1970
                 {
                  dateString=IntegerToString((timeX));
                 }
               else if(dateType==999) // time difference weeks days hours minutes
                 {
                  int timeSign=1;
                  if(timeX<0){timeX=timeX*-1; timeSign=-1;}
                  int weeksD   = MathAbs(timeX/60/60/24/7);
                  timeX        = timeX-weeksD*60*60*24*7;
                  int daysD    = MathAbs(timeX/60/60/24);
                  timeX        = timeX-daysD*60*60*24;
                  int hoursD   = MathAbs((timeX)/60/60);
                  timeX        = timeX-hoursD*60*60;
                  int minutesD = MathAbs((timeX)/60);
                  string weeksDstring="";   if(weeksD>0) weeksDstring=IntegerToString(weeksD)+"wk";
                  string daysDstring="";    if(daysD>0) daysDstring=IntegerToString(daysD)+"day";
                  string hoursDstring="";   if(hoursD>0) hoursDstring=IntegerToString(hoursD)+"hr";
                  string minutesDstring=""; if(minutesD>0) minutesDstring=IntegerToString(minutesD)+"min";
                  dateString=weeksDstring+daysDstring+hoursDstring+minutesDstring;
                  if(timeSign<0) dateString="-"+dateString;
                 }
               else                  // 2014.06.02_10:52
                 {
                  dateString=IntegerToString(TimeYear(timeX))+"."+dayNumberMonth12+"."+dayNumberMonth30+"_"+hours+":"+minutes;
                 }
               return(dateString);
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            void FindDeleteObjectsA(string objectPrefixFindDelete)
              {
               //string ObjectPrefixFindDelete =TimeZone+"_" ;
               int ii;
               for(ii=ObjectsTotal()-1; ii>=0; ii--) //OBJ_TREND
                 {
                  string name=ObjectName(ii); //Print(name);
                  if(StringFind(name,objectPrefixFindDelete,0)==0)
                    {
                     //Print("name ",name, "   objectPrefixFindDelete ",objectPrefixFindDelete);
                     ObjectDelete(name);
                    }
                 }
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            double PipsToPrice(double pips) //PipsToPrice(EntryPipsExtra)
              {
               double points;
               if(Digits== 2) {points= pips/10;    return(NormalizeDouble(points,Digits));}   //JPY pairs
               if(Digits == 3) {points = pips/100;   return(NormalizeDouble(points,Digits));} /////////////////////???????????  
               if(Digits == 4) {points = pips/1000; return(NormalizeDouble(points,Digits));}
               if(Digits == 5) {points = pips/10000; return(NormalizeDouble(points,Digits));}
               return(0);
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            double PriceToPips(double price)
              {
               double pips;
               if(Symbol()=="EURUSD") //Print("********** ",Digits);
               if(Digits==2) {pips=price*10;    return(NormalizeDouble(pips,1));}   //JPY pairs
               if(Digits== 3) {pips =price*100;   return(NormalizeDouble(pips,1));}
               if(Digits==4) {pips=price*10000; return(NormalizeDouble(pips,1));}  //changed from 1000 to 10000
               if(Digits==5) {pips = price*10000; return(NormalizeDouble(pips,1));}
               return(0);
              }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
            bool checkNewBar(int barPeriod,bool initOnly)
              {
               if(barPeriod<=0 && initOnly==true) return(false);
               int timeOldBar=0;
               switch(barPeriod)
                 {
                  case PERIOD_M1:  static int timeOldBarM1 =-1; timeOldBar=timeOldBarM1;  break;
                  case PERIOD_M5:  static int timeOldBarM5 =-1; timeOldBar=timeOldBarM5;  break;
                  case PERIOD_M15: static int timeOldBarM15=-1; timeOldBar=timeOldBarM15; break;
                  case PERIOD_M30: static int timeOldBarM30=-1; timeOldBar=timeOldBarM30; break;
                  case PERIOD_H1:  static int timeOldBarH1 =-1; timeOldBar=timeOldBarH1;  break;
                  case PERIOD_H4:  static int timeOldBarH4 =-1; timeOldBar=timeOldBarH4;  break;
                  case PERIOD_D1:  static int timeOldBarD1 =-1; timeOldBar=timeOldBarD1;  break;
                  case PERIOD_W1:  static int timeOldBarW1 =-1; timeOldBar=timeOldBarW1;  break;
                  case PERIOD_MN1: static int timeOldBarMN1=-1; timeOldBar=timeOldBarMN1; break;
                 }
               int countFrom;
               int count=0;
               if(barPeriod<=PERIOD_H1) {countFrom=PERIOD_H1;} else countFrom=barPeriod;
               while(count<=countFrom-barPeriod)
                 {
                  if(timeOldBar<0 || (TimeMinute(TimeCurrent())==count && TimeCurrent()>=iTime(NULL,barPeriod,0) && count!=TimeMinute(timeOldBar)))
                    {
                     //Print("tttt  ",TimeHour(TimeCurrent()),":",TimeMinute(TimeCurrent()),"  count->",count,"     TimeCurrent->",TimeCurrent(),"    timeNewOpen->",iTime(NULL,barPeriod,0),"    timeOldBarOpen->",timeOldBar);
                     switch(barPeriod)
                       {
                        case PERIOD_M1:  timeOldBarM1 =iTime(NULL,barPeriod,0); return(true);
                        case PERIOD_M5:  timeOldBarM5 =iTime(NULL,barPeriod,0); return(true);
                        case PERIOD_M15: timeOldBarM15=iTime(NULL,barPeriod,0); return(true);
                        case PERIOD_M30: timeOldBarM30=iTime(NULL,barPeriod,0); return(true);
                        case PERIOD_H1:  timeOldBarH1 =iTime(NULL,barPeriod,0); return(true);
                        case PERIOD_H4:  timeOldBarH4 =iTime(NULL,barPeriod,0); return(true);
                        case PERIOD_D1:  timeOldBarD1 =iTime(NULL,barPeriod,0); return(true);
                        case PERIOD_W1:  timeOldBarW1 =iTime(NULL,barPeriod,0); return(true);
                        case PERIOD_MN1: timeOldBarMN1=iTime(NULL,barPeriod,0); return(true);
                       }
                    }
                  count=count+barPeriod; //Print("**************** ",count);
                 }
               return(false);
              }
//+------------------------------------------------------------------+

string strCaution()
{
  string strResult="";
  for(int i=1; i<5; i++)
  {
      if(DayOfWeek()==5 && StringFind(event[i],"NFP",0) >= 0) strResult=strResult+"| NFP |";
      if(DayOfWeek()==5 && StringFind(event[i],"Non-Farm",0) >= 0) strResult=strResult+"| NFP |";
      if(StringFind(event[i],"FOMC",0)>= 0) strResult=strResult+"   FOMC (All Pairs)  ";
      if(StringFind(event[i],"NFP",0) >= 0) strResult=strResult+"   NFP (All Pairs)  ";
      if(StringFind(event[i],"ECB",0) >= 0) strResult=strResult+"   ECB (EUR, GBP, CHF Pairs)  ";
      if(StringFind(event[i],"BOE",0) >= 0) strResult=strResult+"   BOE (GBP Pairs)  ";
      if(StringFind(event[i],"BOJ",0) >= 0) strResult=strResult+"   BOJ (JPY Pairs)  ";
      if(StringFind(event[i],"BOC",0) >= 0) strResult=strResult+"   BOC (CAD Pairs)  ";
      if(StringFind(event[i],"RBA ",0)>= 0) strResult=strResult+"   RBA (AUD Pairs)  ";
  }
 return(strResult);
}      

 bool EventCreate(const long            chart_ID=0,      // chart's ID
                 const string          name="Event",    // event name
                 const int             sub_window=0,    // subwindow index
                 const string          text="Text",     // event text
                 datetime              time=0,          // time
                 const color           clr=clrRed,      // color
                 const int             width=1,         // point width when highlighted
                 const bool            back=true,      // in the background
                 const bool            selection=true, // highlight to move
                 const bool            hidden=false,     // hidden in the object list
                 const long            z_order=0)       // priority for mouse click
  {
//--- if time is not set, create the object on the last bar
   if(!time)
      time=TimeCurrent();
//--- reset the error value
   ResetLastError();
//--- create Event object
   ObjectDelete(name);
   if(!ObjectCreate(chart_ID,name,OBJ_EVENT,sub_window,time,0))
     {
      Print(__FUNCTION__,
            ": failed to create \"Event\" object! Error code = ",GetLastError());
      return(false);
     }
//--- set event text
   ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
//--- set color
   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set anchor point width if the object is highlighted
   ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving event by mouse
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- hide (true) or display (false) graphical object name in the object list
   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
   return(true);
  }
  
     
     
void OnChartEvent(const int id,         // Event identifier  
                  const long& lparam,   // Event parameter of long type
                  const double& dparam, // Event parameter of double type
                  const string& sparam) // Event parameter of string type
  {
//--- the left mouse button has been pressed on the chart

   
   if(id==CHARTEVENT_OBJECT_CLICK)
        {     
         
        if (ObjectType(sparam)==OBJ_VLINE && StringSubstr(sparam,0,5)=="line ") ObjectDelete(sparam);
        
        
        if (ObjectType(sparam)==OBJ_EVENT)
        {
          
          string strTemp="line"+sparam;
          datetime dtTemp=ObjectGet(sparam,OBJPROP_TIME1);
          color clrTemp=ObjectGet(sparam,OBJPROP_COLOR);
          if (ObjectFind(ChartID(),strTemp)==0) {ObjectDelete(strTemp);}
          else {VLine(strTemp,dtTemp,clrTemp);ObjectSetText(strTemp,ObjectDescription(sparam),10,"Arial",clrTemp);}
        }
        
        }
  }
  
  
void VLine(string ObjName,datetime x1,color col)
  {
 
   ObjectDelete(ObjName);
   ObjectCreate(ObjName,OBJ_VLINE,0,x1,0);
   ObjectSet(ObjName,OBJPROP_COLOR,col);
   ObjectSet(ObjName,OBJPROP_RAY,0);
  }          