#property indicator_chart_window
#property indicator_buffers 3

#define NEWS_TITLE		0
#define NEWS_COUNTRY	1
#define NEWS_DATE		2
#define NEWS_TIME		3
#define NEWS_IMPACT		4
#define NEWS_FORECAST	5
#define NEWS_PREVIOUS	6
#define NEWS_GMT			7

#define NEWS_IMPACT_HIGH     3 
#define NEWS_IMPACT_MEDIUM   2
#define NEWS_IMPACT_LOW      1
#define NEWS_IMPACT_UNKNOWN  0

#import "SDSNews.ex4"
void   SDSInitLibrary();
int    SDSGetTotalEvents (); 
bool   SDSGetEvent (int index, string& buffer[]);
int    SDSPreviousEvent (int criticity, string& buffer[]);
int    SDSNextEvent (int criticity, string& buffer[]);
bool   SDSRefreshEvents (bool DailyFXPreferred = false);
void   SDSDeinitLibrary();
void   SDSSetTimeOffset (bool AutoZone, int LocalGMTZone, int ServerGMTZone);
void   SDSSetTimeReference (bool externalreference);
double SDSImpactToNumber(string impact);
datetime TimeGMT();
datetime LocalTimeGMT();
datetime TimeGMTOffset();
datetime AltTimeCurrent();
datetime AltTimeLocal();
datetime TimeCurrentToGMT (datetime currenttime);
datetime TimeGMTToCurrentTime (datetime GMTtime);
datetime TimeLocalToGMT (datetime localtime);
datetime TimeGMTToLocalTime (datetime GMTtime);
#import

#import "user32.dll"
int GetForegroundWindow();
int FindWindowExW(int,int,string,string);
int GetWindowRect(int,int &arr[]);
int GetClientRect(int,int &arr[]);
int SetWindowLongW(int,int,int);
int SetWindowLongPtr(int,int,int);
int GetWindowLongW(int,int);
int GetSystemMenu(int,bool);
int InsertMenuW(int,int,int,int,string);
int SetWindowPos(int,int,int,int,int,int,int);
int GetParent(int);
int GetWindowTextW(int,short &arr[],int);
int ShowWindow(int,int);
int GetClassNameW(int,short &arr[],int);
int GetDlgCtrlID(int);
int GetDlgItem(int,int);
bool IsZoomed(int);
bool InvalidateRect(int,int &arr[],bool);
#import

#define GWL_STYLE         -16 
#define WS_SIZEBOX        0x00040000
#define WS_MINIMIZEBOX    0x00020000
#define WS_MAXIMIZEBOX    0x00010000
#define WS_CAPTION        0x00C00000
#define WS_THICKFRAME     0x00040000
#define WS_SYSMENU        0x00080000
#define WS_MAXIMIZE       0x01000000
#define WS_MINIMIZE       0x20000000
#define WS_DLGFRAME       0x00400000
#define WS_POPUP          0x80000000
#define WS_CHILD          0x40000000
#define WS_THINFRAME      0x00100000
#define MF_STRING         0x00000000
#define MF_BYPOSITION     0x00000400
#define SW_MAXIMIZE       0x0003
#define SC_SIZE           0xF000
#define SC_MAXIMIZE       0xF030
#define SC_MINIMIZE       0xF020
#define SC_RESTORE        0xF120
#define SWP_NOSIZE        0x0001
#define SWP_NOMOVE        0x0002
#define SWP_NOZORDER      0x0004
#define SWP_NOACTIVATE    0x0010
#define SWP_FRAMECHANGED  0x0020

int but[9]={1,5,15,30,60,240,1440,10080,43200};
string butname[9]={"AUD","CAD","CHF","EUR","GBP","JPY","NZD","USD","ALL"};

#define			MAX_SIMULTANEOUS_EVENTS		4

string	__events_selection__			= "--- EVENTS SELECTION ---";
bool 	SelectHighImpactEvents 		= true;
bool 	SelectMediumImpactEvents 	= false;
bool 	SelectLowImpactEvents 		= false;   //true;
bool 	SelectSpeaksEvents 			= false; 		// news items with "Speaks" in them have different characteristics

string	__symbols_selection__		= "--- SYMBOL SELECTION ---";
bool		ReportAllForAll				= true;		// By default is only shows news related with the chart's pair
bool		ReportAllForUSD				= false;
bool    ReportAllForEUR   			= false;
bool    ReportAllForGBP   			= false;
bool    ReportAllForNZD   			= false;		// added and tested by a1ra, seems working OK.
bool    ReportAllForJPY   			= false;
bool    ReportAllForAUD   			= false;
bool    ReportAllForCHF   			= false;
bool    ReportAllForCAD   			= false;
bool    ReportAllForCNY   			= false;

string  __dashboard_configuration_	= "--- DASHBOARD CONFIGURATION ---";
bool		NewsDashBoardShow				= true;			// Choose if we show the Dashboard.
int		NewsDashboardCorner 			= 2;				// Choose which corner to place the Dashboard (0=Upper Left, 1=Upper Right, 2=lower left , 3=lower right)
int		NewsDashboardEvents			= 20;				// Number of events that will be showed at the Dashboard
bool		NewsDashboardSummary			= true;			// If TRUE it will only draw one line per selected event.
color 	NewsDashboardTitleColor 	= Gold;       
color 	NewsDashboardTextColor 		= White;
int 		NewsDashboardTextSize 		= 10;

string  __events_color_				= "--- EVENTS COLORS ---";
color 	ColorImpactHigh      		= Red;			// Color of description / vertical lines if IMPACT is HIGH
color 	ColorImpactMedium       	= Orange;		// Color of description / vertical lines if IMPACT is MEDIUM
color 	ColorImpactLow       		= Khaki;			// Color of description / vertical lines if IMPACT is LOW
color	ColorImpactUndefined 		= Aqua;			// Color of our vertical news line, if no IMPACT has been defined
color	ColorImpactOld					= Gray;			// Color or description is event is OLD.

string  __vertical_lines__			= "--- CHART VERTICAL LINES ---";
bool		LineShowOldEvents				= false;			// Draw vertical lines of past events
bool		LineShowFutureEvents			= false;			// Pending!!!! Draw vertical lines of future events.
color	LineTextColor 					= LightGray;	// Color of our vertical text color 
int		LineTextSize 					= 8;				// Color of our vertical text
int		LineTextLeftShift 			= 900;			// How far away to the left of the line we want to place our vertical news text
int		LineTextRightShift 			= 900;			// How far away to the left of the line we want to place our vertical news text
int		LineTextVerticalShift 		= 21;				// How far away below the ask line we want to place our vertical news text

string  __alerts__						= "--- ALERTS ---";
int		AlertXMinutesBefore			= -1;				// Set to -1 for no Alert
int		AlertYMinutesBefore			= -1;			// Set to -1 for no Alert

string  __configuration__				= "--- ADDITIONAL CONFIGURATION ---";
bool		AutoGMTZones					= false;
int		LocalGMTZone			   	= 1;      // GTM+X
int		BrokerGMTZone					= 2;
// bool		AllowWebUpdates			= true;			// Set this to false when using in another EA or Chart, so that the multiple instances of the indicator dont fight with each other
bool		IsEA_Call						= false;
bool		UseDailyFXAsSource			= false;
bool 	UseGlobalTimeReference 		= false;

double 		ExtMapBuffer0[];	// Contains (minutes until) each news event
double 		ExtMapBuffer1[];	// Contains only most recent and next news event ([0] & [1])
double 		ExtMapBuffer2[];	// Contains impact value for most recent and next news event

int			EventsArray[1000];
int 	   	minsTillNews; 
int			minutesTillNextEvent;
int			indexOfNextEvent;
static int	previousMinute = -1;
datetime 	LastTimeAlert1 = 0;	// Used to make sure we only draw something once per annoucement. Added by MN
int 		  	globalNewsSelectedTotal = 0;
int		  	globalNewsAllTotal = 0;

string 		objectPrefix = "CA*";

int init() {
	// Buffers definitions
	SetIndexStyle(0, DRAW_NONE);
	SetIndexBuffer(0, ExtMapBuffer0);
	SetIndexStyle(1, DRAW_NONE);
	SetIndexBuffer(1, ExtMapBuffer1);
	SetIndexStyle(1, DRAW_NONE);
	SetIndexBuffer(2, ExtMapBuffer2);

	IndicatorShortName("NewsPop");
	
	for(int i = 0; i < ObjectsTotal(); i++) {
	   string objectName	= ObjectName(i);
	   if (StringFind(objectName, objectPrefix, 0) == 0)
		   ObjectDelete(objectName);
	}

	SDSSetTimeReference (UseGlobalTimeReference); 
	SDSSetTimeOffset (AutoGMTZones, LocalGMTZone, BrokerGMTZone);
   SDSInitLibrary ();
   
   previousMinute = -1;

	SDSRefreshEvents (UseDailyFXAsSource);
/*
   for(i=0;i<9;i++) {
   ObjectCreate(0,butname[i],OBJ_BUTTON,0,0,0);
   ObjectSetInteger(0,butname[i],OBJPROP_XSIZE,30);
   ObjectSetInteger(0,butname[i],OBJPROP_YSIZE,15);
//   if (runperiod == but[i])
//      ObjectSetInteger(0,butname[i],OBJPROP_BGCOLOR,clrBlue);
//   else
      ObjectSetInteger(0,butname[i],OBJPROP_BGCOLOR,clrGray);
   ObjectSetInteger(0,butname[i],OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);
   ObjectSetInteger(0,butname[i],OBJPROP_YDISTANCE,40);
   ObjectSetInteger(0,butname[i],OBJPROP_XDISTANCE,40 + i * 35);
   ObjectSetString(0,butname[i],OBJPROP_FONT,"Arial");
   ObjectSetInteger(0,butname[i],OBJPROP_FONTSIZE,8);
   ObjectSetInteger(0,butname[i],OBJPROP_COLOR,clrWhite);
   ObjectSetString(0,butname[i],OBJPROP_TEXT,butname[i]);
   ObjectSetInteger(0,butname[i],OBJPROP_BACK,0);
   ObjectSetInteger(0,butname[i],OBJPROP_STATE,0);
   ObjectSetInteger(0,butname[i],OBJPROP_SELECTABLE,0);
   }

   ObjectCreate(0,"cclose",OBJ_BUTTON,0,0,0);
   ObjectSetInteger(0,"cclose",OBJPROP_XSIZE,50);
   ObjectSetInteger(0,"cclose",OBJPROP_YSIZE,15);
   ObjectSetInteger(0,"cclose",OBJPROP_BGCOLOR,clrRed);
   ObjectSetInteger(0,"cclose",OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);
   ObjectSetInteger(0,"cclose",OBJPROP_YDISTANCE,40);
   ObjectSetInteger(0,"cclose",OBJPROP_XDISTANCE,380);
   ObjectSetString(0,"cclose",OBJPROP_FONT,"Arial");
   ObjectSetInteger(0,"cclose",OBJPROP_FONTSIZE,8);
   ObjectSetInteger(0,"cclose",OBJPROP_COLOR,clrWhite);
   ObjectSetString(0,"cclose",OBJPROP_TEXT,"Close");
   ObjectSetInteger(0,"cclose",OBJPROP_BACK,0);
   ObjectSetInteger(0,"cclose",OBJPROP_STATE,0);
   ObjectSetInteger(0,"cclose",OBJPROP_SELECTABLE,0);
*/
   resizeWindow();

   if (EventSetTimer(60) == false)
      Print("Newspop - Unable to set timer");
	
   OnTimer();

	return(0);
}


int deinit() {
	int i;

	// Cycle through all the Objects looking for the Object Prefix
	for(i = ObjectsTotal() - 1; i >= 0; i--) {
		string objectName	= ObjectName(i);
		if (StringFind(objectName, objectPrefix) == 0)
			ObjectDelete(objectName);
	}
	
	SDSDeinitLibrary();
	
	return(0);
}

void start() {
}

void OnTimer() {
	int i;
	bool skipThisEvent;
	datetime newsTimeGMT;
      
	// check to make sure we are connected, otherwise exit. Added by MN
	if (!IsConnected()) {
		Print("News Indicator is disabled because NO CONNECTION to Broker!");
		return(0);
	}
	
	Print("NEWS NEW MINUTE...Refreshing News from XML file...");

	// Init the buffer array to zero just in case
	ArrayInitialize(ExtMapBuffer0, 0);
	ArrayInitialize(ExtMapBuffer1, 0);
	
	SDSRefreshEvents(UseDailyFXAsSource);

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

	// Parse the loaded events looking for an event to report
	minutesTillNextEvent = 10080;	// (a week)
	globalNewsSelectedTotal = 0;

	for (int index = 0; index < SDSGetTotalEvents(); index++)	{
		skipThisEvent = false;
		
		string eventData[8], nexteventData[8];
		SDSGetEvent (index, eventData);
		
		// Test against filters that define whether we want to skip the selected announcement 
		if (country1 != eventData[NEWS_COUNTRY] && country2 != eventData[NEWS_COUNTRY] &&
				((!ReportAllForUSD || eventData[NEWS_COUNTRY] != "USD") && 
				(!ReportAllForEUR || eventData[NEWS_COUNTRY] != "EUR") && 
				(!ReportAllForGBP || eventData[NEWS_COUNTRY] != "GBP") && 
				(!ReportAllForNZD || eventData[NEWS_COUNTRY] != "NZD") && 
				(!ReportAllForJPY || eventData[NEWS_COUNTRY] != "JPY") && 
				(!ReportAllForAUD || eventData[NEWS_COUNTRY] != "AUD") && 
				(!ReportAllForCAD || eventData[NEWS_COUNTRY] != "CAD") && 
				(!ReportAllForCHF || eventData[NEWS_COUNTRY] != "CHF") && 
				(!ReportAllForCNY || eventData[NEWS_COUNTRY] != "CNY")))
			skipThisEvent = true;
		if (ReportAllForAll)
			skipThisEvent = false;
		if (!SelectHighImpactEvents && eventData[NEWS_IMPACT] == "High") 
			skipThisEvent = true;
		if (!SelectMediumImpactEvents && eventData[NEWS_IMPACT] == "Medium") 
			skipThisEvent = true;
		if (!SelectLowImpactEvents && eventData[NEWS_IMPACT] == "Low") 
			skipThisEvent = true;
		if (!SelectSpeaksEvents && (StringFind(eventData[NEWS_TITLE], "speaks") != -1 || 
								StringFind(eventData[NEWS_TITLE], "Speaks") != -1) ) 
			skipThisEvent = true;
		if (eventData[NEWS_TIME] == "All Day" || 
			 eventData[NEWS_TIME] == "Tentative" ||
			 eventData[NEWS_TIME] == "") 
			skipThisEvent = true;
		newsTimeGMT = StrToTime(eventData[NEWS_GMT]);
		if (newsTimeGMT < TimeGMT())
		   skipThisEvent = true;
		   	   
		// If this event is not skipped, then log it into the draw buffers
		if (!skipThisEvent) {   
			EventsArray[globalNewsSelectedTotal] = index;
			
			// Print(EA_NAME, "EVENT : Title: ", eventData[NEWS_TITLE],
			//					" Country: ", eventData[NEWS_COUNTRY], 
			//					" Date: ", eventData[NEWS_DATE], 
			//					" Time: ", eventData[NEWS_TIME],
			//					" Impact: ", eventData[NEWS_IMPACT],
			//					" Forecast: ", eventData[NEWS_FORECAST], 
			//					" Previous: ", eventData[NEWS_PREVIOUS], 
			//					" GMT: ", eventData[NEWS_GMT],
			//					" NOW: ", TimeToStr(AltTimeCurrent() - TimeGMT(), TIME_MINUTES));	
			
			globalNewsSelectedTotal++;
		}
	}
	for (index = 0; index < globalNewsSelectedTotal; index++)	{
		SDSGetEvent (EventsArray[index], eventData);
		
		// First, convert the announcement time to seconds (in GMT)
		newsTimeGMT = StrToTime(eventData[NEWS_GMT]);
						
		// Now calculate the minutes until this announcement (may be negative).
		// minsTillNews = (newsTimeGMT - LocalTimeGMT()) / 60;
		minsTillNews = (newsTimeGMT - TimeLocalToGMT(AltTimeLocal())) / 60;
								
		// This "if" section added by MN
		// If minsTillNews is zero, then it's the time our news is hit
		if (	((minsTillNews == 0) && (LastTimeAlert1 != newsTimeGMT)) ||
				(!IsEA_Call && LineShowOldEvents && minsTillNews < 0)    ||
				(!IsEA_Call && LineShowFutureEvents && minsTillNews > 0) ){
			DisplayVerticalNews(EventsArray[index], 0); 
			for (int shift = 1; shift < MAX_SIMULTANEOUS_EVENTS; shift++) {
				SDSGetEvent (EventsArray[index + shift], nexteventData);
				if (eventData[NEWS_TIME] == nexteventData[NEWS_TIME])
					DisplayVerticalNews(EventsArray[index + shift], shift);
			}
			// only draw once per announcement
			if ((minsTillNews == 0) && (LastTimeAlert1 != newsTimeGMT))
				LastTimeAlert1 = newsTimeGMT;
		}
			
		// Keep track of the most recent news announcement.
		// Do that by saving each one until we get to the 
		// first annoucement that isn't in the past; i.e.
		// minsTillNews > 0.  Then, keep this one instead for
		// display, but only once the minutes until the next 
		// news is SMALLER than the minutes since the last.
		if (minsTillNews < 0 || MathAbs(minutesTillNextEvent) > minsTillNews) {
				indexOfNextEvent = index;
				minutesTillNextEvent	= minsTillNews;
		}
						
		// Do alert if user has enabled
		if (AlertXMinutesBefore != -1 && minsTillNews == AlertXMinutesBefore)
				Alert(AlertXMinutesBefore, " minutes until news for ", pair, ": ", eventData[NEWS_TITLE]);
		if (AlertYMinutesBefore != -1 && minsTillNews == AlertYMinutesBefore)
				Alert(AlertYMinutesBefore, " minutes until news for ", pair, ": ", eventData[NEWS_TITLE]);
				
		// Buffers are set up as so: 
		// ExtMapBuffer0 contains the time UNTIL each announcement (can be negative)
		// e.g. [0] = -372; [1] = 25; [2] = 450; [3] = 1768 (etc.)
		// ExtMapBuffer1[0] has the mintutes since the last annoucement.
		// ExtMapBuffer1[1] has the mintutes until the next annoucement.
		ExtMapBuffer0[index] = minsTillNews;
	}

	// Cycle through the events array and pick out the most recent 
	// past and the next coming event to put into ExtMapBuffer1. 
	// Put the corresponding impact for these two into ExtMapBuffer2.
	bool first = true;
	ExtMapBuffer1[0] = 99999;
	ExtMapBuffer1[1] = 99999;
	ExtMapBuffer2[0] = 0;
	ExtMapBuffer2[1] = 0;
	for (i = 0; i < globalNewsSelectedTotal; i++)	
	{
		SDSGetEvent (EventsArray[i], eventData);		
		if (ExtMapBuffer0[i] >= 0 && first)
		{
			first = false;
			
			// Put the relevant info into the indicator buffers...

			// Minutes SINCE - - - - - - - - - - - - - - - - - - - - - - - - -
			// (does not apply if the first event of the week has not passed)
			if (i > 0) {
				string previouseventData[8];
				SDSGetEvent (EventsArray[i - 1], previouseventData);
				ExtMapBuffer1[0] = MathAbs(ExtMapBuffer0[i-1]);
				ExtMapBuffer2[0] = SDSImpactToNumber(previouseventData[NEWS_IMPACT]);
			}
			
			// Minutes UNTIL - - - - - - - - - - - - - - - - - - - - - - - - -
			// Check if past the last event.  
			if (ExtMapBuffer0[i] > 0 || (ExtMapBuffer0[i] == 0 && ExtMapBuffer0[i+1] > 0))		
				ExtMapBuffer1[1] = ExtMapBuffer0[i];

			ExtMapBuffer2[1] = SDSImpactToNumber(eventData[NEWS_IMPACT]);
		}
	}	
	
	// If we are past all news events, then neither one will have been 
	// set, so set the past event to the last (negative) minutes
	if (ExtMapBuffer1[0] == 0 && ExtMapBuffer1[1] == 0) {
		ExtMapBuffer1[0] = ExtMapBuffer0[i-1];
		ExtMapBuffer1[1] = 999999;
	}      
	
	if (!IsEA_Call && NewsDashBoardShow && globalNewsSelectedTotal > 0) {
			for( i = 0; i < NewsDashboardEvents; i++ ) 
				ShowDashboard( i, indexOfNextEvent );
//joop
	}
	
	return (0);
}


// Draws the news veritically on the Chart so that we 
// have a visual reference of when it occurs. Added by MN 
void DisplayVerticalNews(int index, int shift) {    
	string eventData[8];
	SDSGetEvent (index, eventData);	

	// datetime TheTime = StrToTime(eventData[NEWS_GMT]);
	string dispCountry = eventData[NEWS_COUNTRY];
	string dispTitle = eventData[NEWS_TITLE];
	int eventImpact = SDSImpactToNumber(eventData[NEWS_IMPACT]);
	datetime theTime = TimeGMTToCurrentTime(StrToTime(eventData[NEWS_GMT]));

	// if (theTime > AltTimeCurrent())
	// 	return;
	
	int BarShift = iBarShift(NULL, 0, theTime);
	double Pivot, Height = 0.0;
	// Calculate our pivot point to determine where to place the news text
	Pivot = (iHigh(NULL, 1440, BarShift + 1) + iLow(NULL, 1440, BarShift + 1) + iClose(NULL, 1440, BarShift + 1)) / 3;  
   
	// If Open price is above the Pivot determine our height
	if (Open[BarShift] > Pivot)
		Height = Low[iLowest(NULL, 0, MODE_LOW, 5, BarShift)] - LineTextVerticalShift * Point;  
	else 
		// Otherwise Open is below Pivot
		Height = High[iHighest(NULL, 0, MODE_HIGH, 5, BarShift)] + LineTextVerticalShift * Point;          

		// Draw a vertical line at the time of the news if it hasnt already been drawn
	color actualcolor;
	string vLineObject = StringConcatenate(objectPrefix, theTime);
	if (ObjectFind(vLineObject) == -1) {
		ObjectCreate(vLineObject, OBJ_TREND, 0, theTime, 0, theTime, iHigh(NULL, 0, BarShift)); 	// experimental
		ObjectSet(vLineObject, OBJPROP_STYLE, STYLE_DOT);
		// Put object in the background behind any other object on the chart
		ObjectSet(vLineObject, OBJPROP_BACK, true);	
		actualcolor = ColorImpactUndefined;
	} else 
		actualcolor = ObjectGet(vLineObject, OBJPROP_COLOR);

	if (eventImpact == NEWS_IMPACT_HIGH && (actualcolor != ColorImpactHigh))
		ObjectSet(vLineObject, OBJPROP_COLOR, ColorImpactHigh);
	else if (eventImpact == NEWS_IMPACT_MEDIUM && 
						(actualcolor != ColorImpactHigh && actualcolor != ColorImpactMedium)) 
		ObjectSet(vLineObject, OBJPROP_COLOR, ColorImpactMedium);
	else if (eventImpact == NEWS_IMPACT_LOW && 
						(actualcolor != ColorImpactHigh && actualcolor != ColorImpactMedium && actualcolor != ColorImpactLow)) 
		ObjectSet(vLineObject, OBJPROP_COLOR, ColorImpactLow);

	
	string headlineObject = StringConcatenate(objectPrefix, theTime, shift);
	if (ObjectFind(headlineObject) == -1) {  
		ObjectCreate(headlineObject, OBJ_TEXT, 0, theTime - LineTextLeftShift + LineTextRightShift * shift, Height); 
		// Rotate the text 90 degrees
		ObjectSet(headlineObject, OBJPROP_ANGLE, 90);
		ObjectSetText(headlineObject, StringConcatenate(dispCountry, " ", dispTitle), LineTextSize, "Arial", LineTextColor);
		// Put object in the background behind any other object on the chart
		ObjectSet(headlineObject, OBJPROP_BACK, true);	
	}

	//force a redraw of our chart
	WindowRedraw();

	return;
}


int ShowDashboard( int id, int idxOfNext ) {
	static int pos_Y = 0;
  
	if( id == 0 ) {
		string ObjectSource = objectPrefix + "Source";
		pos_Y = 4;
		if (ObjectFind(ObjectSource)== -1) {
			ObjectCreate(ObjectSource, OBJ_LABEL, 0, 0, 0);
			ObjectSet(ObjectSource, OBJPROP_CORNER, NewsDashboardCorner);
			ObjectSet(ObjectSource, OBJPROP_XDISTANCE, 10);
			ObjectSet(ObjectSource, OBJPROP_YDISTANCE, pos_Y);       
		}
		
		string newsSource = "";
		if (UseGlobalTimeReference)
		   newsSource = "DailyFX [TESTING]";
		else if (!UseDailyFXAsSource)
		   newsSource = "FOREX FACTORY";
		else 
		   newsSource = "DailyFX";
      ObjectSetText(ObjectSource, "Source: " + newsSource + " (date " + 
										TimeToStr(AltTimeCurrent(), TIME_DATE|TIME_MINUTES) + " / GMT " +
										TimeToStr(TimeLocalToGMT(AltTimeLocal()), TIME_DATE|TIME_MINUTES) + 
										")", NewsDashboardTextSize - 2, "Arial Bold", NewsDashboardTitleColor);	
	} 
	
	pos_Y += NewsDashboardTextSize + 6;

	color NewsDashboardTextColor_  = NewsDashboardTextColor;
	color TxtColorImpact_ = ColorImpactHigh;

	string eventData[8];
	SDSGetEvent (EventsArray[idxOfNext + id], eventData);

	string title   = eventData[NEWS_TITLE];
	string country = eventData[NEWS_COUNTRY];
	string impact  = eventData[NEWS_IMPACT];
	string forecast = eventData[NEWS_FORECAST];
	string previous = eventData[NEWS_PREVIOUS];
	int    minutesTillEvent = (StrToTime(eventData[NEWS_GMT]) - TimeLocalToGMT(AltTimeLocal())) / 60;

   if (minutesTillEvent < 0)
      return;
  	
//	string TimeStr = GenerateTimeString (TimeGMTToLocalTime (StrToTime(eventData[NEWS_GMT])));
	string TimeStr = StringSubstr(eventData[NEWS_GMT],5)+" GMT ";
		
	if (impact == "Low") TxtColorImpact_ = ColorImpactLow;
	if (impact == "Medium") TxtColorImpact_ = ColorImpactMedium;

	string Line1Object = objectPrefix + "L1N" + id;
	string Line2Object = objectPrefix + "L2N" + id;

	if( id != 0 && StringLen (title) == 0 ) return( 0 );

	if (ObjectFind(Line2Object) == -1) {
		ObjectCreate(Line2Object, OBJ_LABEL, 0, 0, 0 );
		ObjectSet(Line2Object, OBJPROP_CORNER, NewsDashboardCorner );
		ObjectSet(Line2Object, OBJPROP_XDISTANCE, 10 );
	} 
	ObjectSet( Line2Object, OBJPROP_YDISTANCE, pos_Y );
	
	if ( minutesTillEvent == 999999) {
		ObjectSetText( Line2Object, " (No more events this week)", NewsDashboardTextSize, "Arial Bold", ColorImpactOld );
	} else {
		if (NewsDashboardSummary) {
			if ( minutesTillEvent < 0 ) 
				TxtColorImpact_ = ColorImpactOld;
			ObjectSetText( Line2Object, country + ": " + TimeStr + title + makeKPIsummary( forecast, previous ), NewsDashboardTextSize, "Arial Bold", TxtColorImpact_ );
			if (ObjectFind(Line1Object) != -1) 
				ObjectDelete(Line1Object);
		} else {
			if ( minutesTillEvent < 0 ) 
				NewsDashboardTextColor_ = ColorImpactOld;

			ObjectSetText( Line2Object, country + ": " + title + makeKPIsummary( forecast, previous ), NewsDashboardTextSize, "Arial Bold", NewsDashboardTextColor_ );

			pos_Y += NewsDashboardTextSize + 4;
			if (ObjectFind(Line1Object) == -1) {
				ObjectCreate( Line1Object, OBJ_LABEL, 0, 0, 0 );
				ObjectSet( Line1Object, OBJPROP_CORNER, NewsDashboardCorner );
				ObjectSet( Line1Object, OBJPROP_XDISTANCE, 10 );
				ObjectSet (Line1Object, OBJPROP_YDISTANCE, pos_Y);
			}
			ObjectSetText( Line1Object, TimeStr + impact + " impact event [GMT " + eventData[NEWS_TIME] + "]", NewsDashboardTextSize, "Arial Bold", TxtColorImpact_ );
		}
	}

  return( 0 );
}

string makeKPIsummary( string f, string p ) {
	if( StringLen( f ) == 0 && StringLen( p ) == 0 ) 
		return( "" );
	if( StringLen( f ) > 0 && StringLen( p ) == 0 ) 
		return( "  (" + f + "/-.-)" );
	if( StringLen( f ) == 0 && StringLen( p ) >  0 ) 
		return( "  (-.-/" + p + ")" );
	return( "  (" + f + "/" + p + ")" );
}


string GenerateTimeString (datetime time) {
	int    minutesTillEvent = (time - AltTimeLocal()) / 60;
	// string times = TimeToStr (TimeGMTToCurrentTime (StrToTime(eventData[NEWS_GMT])), TIME_DATE | TIME_MINUTES);

	int Days, Hours, Mins; // to display time in days, hours, minutes
	string TimeStr;
	
	// If the time is 0 or negative, we want to say 
	// "xxx mins SINCE ... news event", else say "UNTIL ... news event"
	string 	sinceUntil = "until ";
	int 	dispMins = minutesTillEvent;
	if (minutesTillEvent <= 0) {
		sinceUntil = "since ";
		dispMins *= -1;
	}
		
	// added the following to show hours and days for longer durations
	// this could be enhanced to suppress 0 hours and 0 minutes
	if (dispMins == 999999) {
		TimeStr = " (No more events this week)";
	} else if (dispMins < 60) {
		TimeStr = dispMins + " mins ";
	} else { // time is 60 minutes or more
		Hours = MathRound(dispMins / 60);
		Mins = dispMins % 60;
		if (Hours < 24) { // less than a day: show hours and minutes
			TimeStr = Hours + " hrs " + Mins + " mins ";
		} else { // days, hours, and minutes
			Days = MathRound(Hours / 24);
			Hours = Hours % 24;
			TimeStr = Days + " days " + Hours + " hrs " + Mins + " mins ";
		}
	}
	
	return (TimeStr + sinceUntil);
}
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   if(id==CHARTEVENT_OBJECT_CLICK)
     {

      string clickedChartObject=ObjectGetString(0,sparam,OBJPROP_TEXT);
      string clickedObjectName = sparam;

      if (clickedChartObject == "Close") {
            ChartClose(0);
         return;
      }
      for (int i=0;i<9;i++) {
         if (clickedChartObject == butname[i]) {
            ChartSetSymbolPeriod(0,Symbol(),but[i]);
            return;
         }  
      }
   }
}
//+------------------------------------------------------------------+
void resizeWindow() {

int wndh = WindowHandle(Symbol(),Period());
   if (wndh == -1)
      return;

int wndhp = GetParent(wndh);
   if (wndhp == -1)
      return;

int wnds = GetWindowLongW(wndhp,GWL_STYLE);

   wnds &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
//   wnds &= WS_THINFRAME;

   SetWindowLongW(wndhp,GWL_STYLE,wnds);
   SetWindowPos(wndhp,NULL,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED);      
   SetWindowPos(wndhp,0,100,100,600,500,SWP_NOZORDER);      
   
}  
