FFCal

FFCal

官方版无广告296

更新日期:2022-02-23分类标签: 语言:中文平台:没限制

13 人已下载 手机查看

FFCal

 

//===================================================================================
// Last revision 21, September 2014 – Unicode strings on grabWeb and FileSeek
// FFCal.mq4
// Copyright © 2006, Derk Wehler
// (derkwehler@gmail.com)
// Written in cooperation with: http://www.forexfactory.com
//
// $Workfile:: FFCal.mq4 $
// $Revision:: 20 $
// $Author:: Derk $
// $Date:: 7/07/09 5:40a $
//
// This “indicator” calls DLLs to fetch a special XML file from the
// ForexFactory web site. It then parses it and writes it out as a .CSV
// file, which it places in the folder: experts/files so that IsNewsTime()
// can use that file to tell if it is near announcement time.
//
// It does this once when it starts up and once per 6 hours in case there
// have been any updates to the annoucement calendar. In order to lessen
// sudden traffic on the FF site, it refreshes every 6 hours on a random
// minute.
//
// SAMPLE CALLS TO THE INDICATOR:
//
// int minutesSincePrevEvent =
// iCustom(NULL, 0, “FFCal”, true, true, false, true, true, 1, 0);
//
// int minutesUntilNextEvent =
// iCustom(NULL, 0, “FFCal”, true, true, false, true, true, 1, 1);
//
// // Use this call to get ONLY impact of previous event
// int impactOfPrevEvent =
// iCustom(NULL, 0, “FFCal”, true, true, false, true, true, 2, 0);
//
// // Use this call to get ONLY impact of nexy event
// int impactOfNextEvent =
// iCustom(NULL, 0, “FFCal”, true, true, false, true, true, 2, 1);
//
//
// EXAMPLE CODE FOR USE IN AN EA:
// (NOTE I HAVE PUT IN CODE TO CALL THE INDICATOR ONLY ONCE PER MINUTE)
//
// // EA Setting variables
// extern int MinsBeforeNews = 60; // mins before an event to stay out of trading
// extern int MinsafterNews = 60; // mins after an event to stay out of trading
//
// // Global variable at top of file
// bool NewsTime;
//
// // Function to check if it is news time
// void NewsHandling()
// {
// static int PrevMinute = -1;
//
// if (Minute() != PrevMinute)
// {
// PrevMinute = Minute();
//
// int minutesSincePrevEvent =
// iCustom(NULL, 0, “FFCal”, true, true, false, true, true, 1, 0);
//
// int minutesUntilNextEve nt =
// iCustom(NULL, 0, “FFCal”, true, true, false, true, true, 1, 1);
//
// NewsTime = false;
// if ((minutesUntilNextEvent <= MinsBeforeNews) ||
// (minutesSincePrevEvent <= MinsAfterNews))
// {
// NewsTime = true;
// }
// }
// }//newshandling
//
//=============================================================================
//
// OTHER CREDIT DUE
// (For GrebWeb and LogUtils functionality (see end of this flie)
//
// 2/14/2007: Robert Hill added code for using text objects instead
// of Comment() for easier reading
//
// 2/25/2007: Paul Hampton-Smith for his TimeZone DLL code
// 3/31/2007: Code replaces by simpler method from BurgerKing
//
// 2/26/2007: Mike Nguyen added the following things:
// (search text for “Added by MN”)
//
// – Connection test so that MT4 doesnt hang when
// there is no server connection
// – Fixed some minor syntax because was getting
// “too many files open error…”
// – Added vertical lines and vertical news text so that
// we have a visual reference of when the news happened.
// – Now supports and correctly draws two simultaneous news
// announcements
// – Added text to say “xx min SINCE event…” after the
// event as past
// – Clean up old Objects left behind on old news annoumcents
// – Now “Back Draws” Old news headlines onto the chart
// – Now can choose which corner of the chart to place the
// headlines
//
// 4/2/2007: Mike Nguyen added the following things:
// (search text for “Added by MN”)
// – Added ability to disable Web/URL updates. This is so that the
// multiple instances of the indicator used by other charts or EAs
// dont fight with each other (Error code 4103)
// – Fixed deleting OBJ_TREND, only deletes its own Trend Lines
// objects instead of all OBJ_TREND objects
// – Fixed deleting OBJ_TEXT, only deletes its own Headlines
// instead of all text
// – Made file name global and indicator now deletes the xml file
// each time the indicator is put on or removed from chart. Fixed
// one case of divide by zero where multiple charts indicator is
// on was trying to overwrite the same file (forces a new
// download of the xml)
//
// 4/29/2007: Derk Wehler
// – Fixed problem where indicator returns zero for “Minutes Until
// Next Event” when there are no more events for the week for
// that currency pair. That caused EAs calling it to think that
// it was always new time. Instead, we now set it to a flag
// value, which EAs can test for.
//
// 5/16/2007: Derk Wehler
// – Added sample code to header
// – Changed variable name from DispOldNews to DispVertNews
//
// 6/02/2007: Derk Wehler (thanks to “Flourishing”)
// – Changed how often it updates the file from the FF site web
// page. Now it uses a global variable, so that when you have
// it running on multiple charts, it should only update once
// every 4 hours for all of them.
//
// 6/05/2007: Derk Wehler
// – Fixed logHandle error by resetting to -1 when closed
// – Added “NeedToGetFile” variable for getting the XML if it
// does not already exist
// – Added extern “SaveXmlFiles”, so that when FFCal de-inits,
// the user can choose whether or not to delete old XML files
//
//=============================================================================
//+—————————————————————————+
//| WinInet.mqh |
//| Paul Hampton-Smith |
//| paul1000@pobox.com |
//| |
//| This include has been adapted from the groundbreaking GrabWeb script |
//| developed by Adbi that showed me how to import functions from wininet.dll |
//|—————————————————————————|
//| grabweb.mq4 |
//| Copyright © 2006, Abhi |
//| http://www.megadelfi.com/experts/ |
//| E-mail: grabwebexpert{Q)megadelfi.com |
//| fix my e-mail address before mailing me 😉 |
//+—————————————————————————+
/*
IDEAS FOR ADDITIONS:

* A text lable of what the news was and when it was, e.g
“USD CPI m/m @ [broker time here]” at the top or bottom within the shaded area.

* Label the number of pips it went in its initial direction and how much it
retraced…of course you’d have to come up with a convention for measuring
movement. Or you could label what price was just prior to news then labels
the next two price exteremes. I think it would be nice to have the numbers
right under/over the candle that produced the extremes for whatever timeframe
you are in.

* Label the volume count for the candle that included the news in it…whatever
timeframe your in. So I could switch from 1 min. to 5 min. to 15 min.
timeframes and get different vol. counts for the bar that included the news.

*/

#property copyright “Copyright © 2006, Derk Wehler”
#property link “http://www.forexfactory.com”

#property indicator_chart_window
#property indicator_buffers 3

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

//====================================================================================
//====================================================================================
//====================================================================================
//====================================================================================
//====================================================================================
//====================================================================================
//====================================================================================

extern bool IncludeHigh = true;
extern bool IncludeMedium = true;
extern bool IncludeLow = false; //true;
extern bool IncludeSpeaks = true; // news items with “Speaks” in them have different characteristics
extern bool IsEA_Call = false;
extern int OffsetHours = 0; //-1;
extern 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
extern int Alert1MinsBefore = 0; // Set to -1 for no Alert
extern int Alert2MinsBefore = -1; // Set to -1 for no Alert
extern bool ReportAllForUSD = true;
extern bool ReportAllForEUR = true;
extern bool ReportAllForGBP = true;
// added and tested by a1ra, seems working OK.
extern bool ReportAllForNZD = true;
extern bool ReportAllForJPY = true;
extern bool ReportAllForAUD = true;
extern bool ReportAllForCHF = true;
extern bool ReportAllForCAD = true;
extern bool ReportAllForCNY = false;

extern bool EnableLogging = false; // Perhaps remove this from externs once its working well
extern bool ShowNextTwoEvents = true;
extern bool ShowVertNews = false;
extern int TxtSize = 10;
extern color TxtColorTitle = Gold; //LightGray;
extern color TxtColorNews = DeepSkyBlue;
extern color TxtColorImpact = Red;
extern color TxtColorPrevious = Peru;
extern color TxtColorForecast = Lime;
extern int VertTxtShift = 21; // How far away below the ask line we want to place our vertical news text
extern int VertLeftLineShift = 900; // How far away to the left of the line we want to place our vertical news text
extern int VertRightLineShift = 200; // How far away to the left of the line we want to place our vertical news text
extern color VertLineColor = SlateBlue; // Color of our vertical news line
extern color VertTxtColor = Black; // Color of our vertical text color
extern int VertTxtSize = 8; // Color of our vertical text
extern int NewsCorner = 1; // Choose which corner to place headlines 0=Upper Left, 1=Upper Right, 2=lower left , 3=lower right
extern bool SaveXmlFiles = false; // If true, this will keep the daily XML files

int DebugLevel = 5;

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

//string sUrl = “http://www.forexfactory.com/calendar.php”;

string sUrl = “https://nfs.faireconomy.media/ff_calendar_thisweek.xml”;
int xmlHandle;
int logHandle = -1;
int BoEvent, finalend, end, i;
int begin;
string mainData[100][7];
int minsTillNews;
string sData, csvoutput;
string commentStr;
int tmpMins;
int idxOfNext;
int dispMinutes[2];
string dispTitle[2],
dispCountry[2],
dispImpact[2],
dispForecast[2],
dispPrevious[2];

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>” };
//old tag
//string sTags[7] = { “<title>”, “<country>”, “<date>”, “<time>”, “<impact>”, “<forecast>”, “<previous>” };
//string eTags[7] = { “</title>”, “</country>”, “</date>”, “</time>”, “</impact>”, “</forecast>”, “</previous>” };

static bool NeedToGetFile = false;
static int PrevMinute = -1;
static int RefreshMin = 0;
static int RefreshHour = 0;

datetime LastTimeAlert1 = 0; // Used to make sure we only draw something once per annoucement. Added by MN
string xmlFileName; // Made global. added by MN

int init()
{
if (DebugLevel > 0)
Print(“In Init()…\n”);

SetIndexStyle(0, DRAW_NONE);
SetIndexBuffer(0, ExtMapBuffer0);

SetIndexStyle(1, DRAW_NONE);
SetIndexBuffer(1, ExtMapBuffer1);

SetIndexStyle(1, DRAW_NONE);
SetIndexBuffer(2, ExtMapBuffer2);

IndicatorShortName(“FFCal”);
// SetIndexLabel(0, “MinsBeforeNews”);
// SetIndexLabel(1, “MinsAfterNews”);
//————————————————————-
MathSrand(TimeLocal()); //random number
RefreshMin = (MathRand() % 60);
RefreshHour = (MathRand() % 6);
if (DebugLevel > 0)
{ Print(“RefreshMin == “, RefreshMin);
Print(“RefreshHour == “, RefreshHour);
}
//————————————————————

return(0);
}

int deinit()
{
int i2;

ObjectDelete(“Sponsor”);

ObjectDelete(“Minutes”);
ObjectDelete(“Impact”);
ObjectDelete(“Previous”);
ObjectDelete(“Forecast”);

ObjectDelete(“Minutes2”);
ObjectDelete(“Impact2”);
ObjectDelete(“Previous2”);
ObjectDelete(“Forecast2”);

// Cycle through all the Objects looking for the Vertical Line. //added by MN
for(i2=ObjectsTotal()-1; i2 >= 0; i2–)
{
string VerticalLineName = ObjectName(i2);
if (StringSubstr(VerticalLineName, 0, 5) != “vLine”)
continue;

ObjectDelete(VerticalLineName);
}

// Cycle through all the Objects looking for the HeadLine text. //added by MN
for (i2=ObjectsTotal()-1; i2 >= 0; i2–)
{
string HeadlineName = ObjectName(i2);
if (StringSubstr(HeadlineName, 0, 8) != “Headline”)
continue;

ObjectDelete(HeadlineName);
}

// Fixed one case of divide by zero where multiple charts
// indicator is on was trying to overwrite the same file
xmlFileName = GetXmlFileName();
xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ|FILE_WRITE);

// File does not exist if FileOpen return -1 or if GetLastError = ERR_CANNOT_OPEN_FILE (4103)
if (xmlHandle >= 0)
{
// Since file exists, Close what we just opened
FileClose(xmlHandle);

// Delete our news file and redownload a new one to prevent a remainder from zero divide error
if (!SaveXmlFiles)
FileDelete(xmlFileName);
}

return(0);
}

string GetXmlFileName()
{
return (Month() + “-” + Day() + “-” + Year() + “-” + Symbol() + Period() + “-” + “FFCal.xml”);
}
//C:\Program Files\IBFX Australia\experts\files\2-16-2011-EURUSD240-FFCal.xml

int start()
{
int newsIdx = 0;
int nextNewsIdx = -1;
int next;
string myEvent;
bool skip;
datetime newsTime;
ulong file_size = 0;
ulong data_size = 0;

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

// If we are not logging, then do not output debug statements either
if (!EnableLogging)
DebugLevel = 0;

commentStr = “FOREX FACTORY CALENDAR”;

// Added this section to check if the XML file already exists.
// If it does NOT, then we need to set a flag to go get it
xmlFileName = GetXmlFileName();
xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ);
file_size = FileSize(xmlHandle);

// File does not exist if FileOpen return -1 or if GetLastError = ERR_CANNOT_OPEN_FILE (4103)
if (xmlHandle >= 0)
{
// Since file exists, close what we just opened
FileClose(xmlHandle);
NeedToGetFile = false;
}
else
NeedToGetFile = true;

//added by MN. Set this to false when using in another EA or Chart, so that the multiple
//instances of the indicator dont fight with each other
if (AllowWebUpdates)
{
// New method: Use global variables so that when put on multiple charts, it
// will not update overly often; only first time and every 4 hours
if (DebugLevel > 1)
Print(GlobalVariableGet(“LastUpdateTime”) + ” ” + (TimeCurrent() – GlobalVariableGet(“LastUpdateTime”)));

if (file_size == 0 || NeedToGetFile || GlobalVariableCheck(“LastUpdateTime”) == false || (TimeCurrent() – GlobalVariableGet(“LastUpdateTime”)) > 14400)
{
if (DebugLevel > 1)
Print(“sUrl == “, sUrl);

if (DebugLevel > 0)
Print(“Grabbing Web, url = “, sUrl);

// THIS CALL WAS DONATED BY PAUL TO HELP FIX THE RESOURCE ERROR
GrabWeb(sUrl, sData);

if (DebugLevel > 0)
{
Print(“Opening XML file…\n”);
Print(sData);
}

// Delete existing file
FileDelete(xmlFileName);

// Write the contents of the ForexFactory page to an .htm file
// If it is still open from the above FileOpen call, close it.
xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_WRITE);
if (xmlHandle < 0)
{
if (DebugLevel > 0)
Print(“Can\’t open new xml file, the last error is “, GetLastError());
return(false);
}
FileWriteString(xmlHandle, sData, StringLen(sData));
FileClose(xmlHandle);

if (DebugLevel > 0)
Print(“Wrote XML file…\n”);

// THIS BLOCK OF CODE DONATED BY WALLY TO FIX THE RESOURCE ERROR
//— Look for the end XML tag to ensure that a complete page was downloaded —//
end = StringFind(sData, “</weeklyevents>”, 0);

if (end <= 0)
{
Alert(“FFCal Error – Web page download was not complete!”);
return(false);
}
else
{
// set global to time of last update
GlobalVariableSet(“LastUpdateTime”, TimeCurrent());
}

//——————————————————————————-//
}
} //end of allow web updates

// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Perform remaining checks once per minute
if (!IsEA_Call && Minute() == PrevMinute)
return (true);
PrevMinute = Minute();
// Print(“FFCal NEW MINUTE…Refreshing News from XML file…”);

// Open the log file (will not open if logging is turned off)
OpenLog(“FFCal”);

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

// Open the XML file
xmlHandle = FileOpen(xmlFileName, FILE_BIN|FILE_READ);
if (xmlHandle < 0)
{
Print(“Can\’t open xml file: “, xmlFileName, “. The last error is “, GetLastError());
return(false);
}

if (DebugLevel > 0)
Print(“XML file open must be okay size = “, file_size, ” handle = “, xmlHandle);

// Read in the whole XML file
// Ave file length == ~7K, so 65536 should always read whole file

sData = FileReadString(xmlHandle, 65536);
bool pnt = FileSeek(xmlHandle, 0, 0); //senza non funziona

file_size = FileSize(xmlHandle);
data_size = StringLen(sData);

//if (((ulong)StringLen(sData)) < FileSize(xmlHandle))
// sData = sData + FileReadString(xmlHandle, FileSize(xmlHandle));
if (data_size < file_size)
sData = sData + FileReadString(xmlHandle, file_size);

// Because MT4 build 202 complained about too many files open and MT4 hung. Added by MN
if (xmlHandle > 0)
FileClose(xmlHandle);

// Get the currency pair, and split it into the two countries
string pair = Symbol();
string cntry1 = StringSubstr(pair, 0, 3);
string cntry2 = StringSubstr(pair, 3, 3);
if (DebugLevel > 0)
Print(“cntry1 = “, cntry1, ” cntry2 = “, cntry2);

if (DebugLevel > 0)
Log(“Weekly calendar for ” + pair + “\n\n”);

// ————————————————-
// Parse the XML file looking for an event to report
// ————————————————-

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
if (end > begin && end != -1)
{
// Get data between start and end tag
mainData[newsIdx][i] = StringSubstr(myEvent, begin, end – begin);
}
}
}

// for (i=6; i >= 0; i–)
// Print(sTags[i], ” = “, mainData[newsIdx][i]);

// = – = = – = = – = = – = = – = = – = = – = = – = = – = = – =
// Test against filters that define whether we want to
// skip this particular annoucement
if (cntry1 != mainData[newsIdx][COUNTRY] && cntry2 != mainData[newsIdx][COUNTRY] &&
((!ReportAllForUSD || mainData[newsIdx][COUNTRY] != “USD”) &&
(!ReportAllForEUR || mainData[newsIdx][COUNTRY] != “EUR”) &&
(!ReportAllForGBP || mainData[newsIdx][COUNTRY] != “GBP”)&&
(!ReportAllForNZD || mainData[newsIdx][COUNTRY] != “NZD”)&&
(!ReportAllForJPY || mainData[newsIdx][COUNTRY] != “JPY”)&&
(!ReportAllForAUD || mainData[newsIdx][COUNTRY] != “AUD”)&&
(!ReportAllForCAD || mainData[newsIdx][COUNTRY] != “CAD”)&&
(!ReportAllForCHF || mainData[newsIdx][COUNTRY] != “CHF”)&&
(!ReportAllForCNY || mainData[newsIdx][COUNTRY] != “CNY”)))
skip = true;

if (!IncludeHigh && mainData[newsIdx][IMPACT] == “High”)
skip = true;
if (!IncludeMedium && mainData[newsIdx][IMPACT] == “Medium”)
skip = true;
if (!IncludeLow && mainData[newsIdx][IMPACT] == “Low”)
skip = true;
if (!IncludeSpeaks && (StringFind(mainData[newsIdx][TITLE], “speaks”) != -1 ||
StringFind(mainData[newsIdx][TITLE], “Speaks”) != -1) )
skip = true;
if (mainData[newsIdx][TIME] == “All Day” ||
mainData[newsIdx][TIME] == “Tentative” ||
mainData[newsIdx][TIME] == “”)
skip = true;
// = – = = – = = – = = – = = – = = – = = – = = – = = – = = – =

// If not skipping this event, then log it into the draw buffers
if (!skip)
{
// If we got this far then we need to calc the minutes until this event
//
// First, convert the announcement time to seconds (in GMT)
newsTime = StrToTime(MakeDateTime(mainData[newsIdx][DATE], mainData[newsIdx][TIME]));

// Now calculate the minutes until this announcement (may be negative)
minsTillNews = (newsTime – myTimeGMT()) / 60;
if (DebugLevel > 0)
{
Log(“FOREX FACTORY\nTitle: ” + mainData[newsIdx][TITLE] + “\n” + minsTillNews + “\n\n”);
}

// This “if” section added by MN
// If minsTillNews is zero, then it’s the time our news is hit
if ((minsTillNews == 0) && (LastTimeAlert1 != newsTime))
{
// draw the 1st news event onto the chart vertically so
// we have a visual record of when it occured
DisplayVerticalNews(dispTitle[0], dispCountry[0], 0);

// If there is a 2nd simultaneous news event,
// display the 2nd news event
if (dispMinutes[0] == dispMinutes[1])
DisplayVerticalNews(dispTitle[1], dispCountry[1], 1);

// only draw once per announcement
LastTimeAlert1 = newsTime;
}

// This “if” section added by MN
// Back Draw old news onto the chart. Added by MN
if (ShowVertNews && !IsEA_Call)
{
// Back draw 1st news headline
DisplayOldNews(mainData[newsIdx][TITLE], mainData[newsIdx][COUNTRY], 0, StrToTime(MakeDateTime(mainData[newsIdx][DATE], mainData[newsIdx][TIME])));

//if there is a 2nd simultaneously occuring news headline, draw that onto the chart as well
if (mainData[newsIdx][TIME] == mainData[newsIdx+1][TIME])
DisplayOldNews(mainData[newsIdx+1][TITLE], mainData[newsIdx+1][COUNTRY], 1,
StrToTime(MakeDateTime(mainData[newsIdx+1][DATE], mainData[newsIdx+1][TIME])));
}

// 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.
// Print(“Mins till event: “, minsTillNews);
if (minsTillNews < 0 || MathAbs(tmpMins) > minsTillNews)
{
idxOfNext = newsIdx;
tmpMins = minsTillNews;
}

Log(“Weekly calendar for ” + pair + “\n\n”);
if (DebugLevel > 0)
{
Log(“FOREX FACTORY\nTitle: ” + mainData[newsIdx][TITLE] +
“\nCountry: ” + mainData[newsIdx][COUNTRY] +
“\nDate: ” + mainData[newsIdx][DATE] +
“\nTime: ” + mainData[newsIdx][TIME] +
“\nImpact: ” + mainData[newsIdx][IMPACT] +
“\nForecast: ” + mainData[newsIdx][FORECAST] +
“\nPrevious: ” + mainData[newsIdx][PREVIOUS] + “\n\n”);
}

// Do alert if user has enabled
if (Alert1MinsBefore != -1 && minsTillNews == Alert1MinsBefore)
Alert(Alert1MinsBefore, ” minutes until news for “, pair, “: “, mainData[newsIdx][TITLE]);
if (Alert2MinsBefore != -1 && minsTillNews == Alert2MinsBefore)
Alert(Alert2MinsBefore, ” minutes until news for “, pair, “: “, mainData[newsIdx][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[newsIdx] = minsTillNews;
newsIdx++;
}
}

// 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;
string outNews = “Minutes until news events for ” + pair + ” : “;
for (i=0; i < newsIdx; i++)
{
outNews = outNews + ExtMapBuffer0[i] + “, “;
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)
{
ExtMapBuffer1[0] = MathAbs(ExtMapBuffer0[i-1]);
ExtMapBuffer2[0] = ImpactToNumber(mainData[i-1][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] = ImpactToNumber(mainData[i][IMPACT]);
}

// Also use this loop to set which information to display
if (i == idxOfNext)
{
dispTitle[0] = mainData[i][TITLE];
dispCountry[0] = mainData[i][COUNTRY];
dispImpact[0] = mainData[i][IMPACT];
dispForecast[0] = mainData[i][FORECAST];
dispPrevious[0] = mainData[i][PREVIOUS];
dispMinutes[0] = ExtMapBuffer0[i];
}

if (i == idxOfNext + 1)
{
dispTitle[1] = mainData[i][TITLE];
dispCountry[1] = mainData[i][COUNTRY];
dispImpact[1] = mainData[i][IMPACT];
dispForecast[1] = mainData[i][FORECAST];
dispPrevious[1] = mainData[i][PREVIOUS];
dispMinutes[1] = ExtMapBuffer0[i];
}

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

// Ensures that we clean up so that we get old text
// left behind on old news annoumcents. Added by MN
ObjectDelete(“Impact”);
ObjectDelete(“Previous”);
ObjectDelete(“Forecast”);

ObjectDelete(“Impact2”);
ObjectDelete(“Previous2”);
ObjectDelete(“Forecast2”);
}

// For debugging…Print the tines until news events, as a “Comment”
if (DebugLevel > 0)
{
Print(outNews);
Print(“LastMins (ExtMapBuffer1[0]) = “, ExtMapBuffer1[0]);
Print(“NextMins (ExtMapBuffer1[1]) = “, ExtMapBuffer1[1]);
}

if (!IsEA_Call)
OutputToChart();

if (logHandle > 0)
{
FileClose(logHandle);
logHandle = -1;
}

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(string dispVTitle, string dispVCountry, int shift)
{
double Pivot, Height = 0.0;

// Calculate our pivot point to determine where to place the news text
Pivot = (iHigh(NULL, 1440, 1) +
iLow(NULL, 1440, 1) +
iClose(NULL, 1440, 1)) / 3;

// If Open price is above the Pivot determine our height
if (Open[0] > Pivot)
Height = Low[iLowest(NULL,0,MODE_LOW,5,0)] – VertTxtShift*Point;
else
// Otherwise Open is below Pivot
Height = High[iHighest(NULL,0,MODE_HIGH,5,0)] + VertTxtShift*Point;

if (shift == 0)
{
// Draw a vertical line at the time of the news if it hasnt already been drawn
if (ObjectFind(“vLine” + Time[0]) == -1)
{
ObjectCreate(“vLine” + Time[0], OBJ_TREND, 0, Time[0], 0, Time[0], High[0]); // experimental
ObjectSet(“vLine” + Time[0], OBJPROP_COLOR, VertLineColor);
ObjectSet(“vLine” + Time[0], OBJPROP_STYLE, STYLE_DOT);

// Put object in the background behind any other object on the chart
ObjectSet(“vLine” + Time[0], OBJPROP_BACK, true);
}

// Place our news if it hasnt already been placed on our chart
if (ObjectFind(“Headline” + Time[0]) == -1)
{
// For x value use Time[0], for y value find the lowest
// bar within the last 10 bars, subtract by VertTxtShift
// and used that as our y coordinate
ObjectCreate(“Headline” + Time[0], OBJ_TEXT, 0,
Time[0] – VertLeftLineShift, Height);

// Rotate the text 90 degrees
ObjectSet(“Headline” + Time[0], OBJPROP_ANGLE, 90);

ObjectSetText(“Headline” + Time[0],
“News: ” + dispVCountry + ” ” + dispVTitle,
VertTxtSize, “Arial”, VertTxtColor);
}
}
// Draw second news headline
else
{
//place our news if it hasnt already been placed on our chart
if (ObjectFind(“Headline” + Time[0]+”s”) == -1)
{
// For x value use Time[0], for y value find the lowest
// bar within the last 10 bars, subtract by VertTxtShift
// and used that as our y coordinate
ObjectCreate(“Headline” + Time[0] + “s”, OBJ_TEXT, 0,
Time[0] + VertRightLineShift, Height);

// Rotate the text 90 degrees
ObjectSet(“Headline” + Time[0] + “s”, OBJPROP_ANGLE, 90);

ObjectSetText(“Headline” + Time[0] + “s”,
“News: ” + dispVCountry + ” ” + dispVTitle,
VertTxtSize, “Arial”, VertTxtColor);
}
}

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

return;
}

// Back Draw Old news veritically on the Chart so that we
// have a visual reference of when it did occur. Added by MN
void DisplayOldNews(string dispOTitle, string dispOCountry, int shift, datetime TheTime)
{
int BarShift;
double Pivot;
double Height = 0.0;

// We have TheTime, now we need the shift so we can
// access this Bar’s High/Low/Close information
BarShift = iBarShift(NULL, 0, TheTime);

// Calculate our pivot point to determine where to place the news text
Pivot = (iHigh(NULL, 1440, BarShift) +
iLow(NULL, 1440, BarShift) +
iClose(NULL, 1440, BarShift)) / 3;

// If open price is above the Pivot, determine our height
if (Open[BarShift] > Pivot)
Height = Low[iLowest(NULL, 0, MODE_LOW, 5, BarShift)] – VertTxtShift*Point;

// Otherwise Open is below Pivot
else
Height = High[iHighest(NULL, 0, MODE_HIGH, 5, BarShift)] + VertTxtShift*Point;

//Print(“Title recieved : ” + dispTitle + ” Country Recieved: ” + dispCountry + ” Date and time Recieved: ” + TheTime);

// We only want to vertically draw the news if it hasnt occured yet
if (TheTime < Time[0])
{
// Draw the first news headline
if (shift == 0)
{
// Draw a vertical line at the time of the
// news if it hasnt already been drawn
if (ObjectFind(“vLine” + TheTime) == -1)
{
ObjectCreate(“vLine” + TheTime, OBJ_TREND, 0, TheTime, 0, TheTime, High[0]); //experimental
ObjectSet(“vLine” + TheTime, OBJPROP_COLOR, VertLineColor);
ObjectSet(“vLine” + TheTime, OBJPROP_STYLE, STYLE_DOT);

// put object in the background behind any other object on the chart
ObjectSet(“vLine” + TheTime, OBJPROP_BACK, true);
}

// Place our news if it hasnt already been placed on our chart
if (ObjectFind(“Headline” + TheTime) == -1)
{
// For x value use Time[0], for y value find the lowest bar within the last 10 bars, subtract by VertTxtShift and used that as our y coordinate
ObjectCreate(“Headline” + TheTime, OBJ_TEXT, 0, TheTime – VertLeftLineShift, Height);

// rotate the text 90 degrees
ObjectSet(“Headline” + TheTime, OBJPROP_ANGLE, 90);
ObjectSetText(“Headline” + TheTime, “News: ” + dispOCountry + ” ” + dispOTitle,
VertTxtSize, “Arial”, VertTxtColor);
}
}

// Draw second news headline
else
{
//place our news if it hasnt already been placed on our chart
if (ObjectFind(“Headline” + TheTime + “s”) == -1)
{
// For x value use Time[0], for y value find the lowest bar within the
// last 10 bars, subtract by VertTxtShift and used that as our y coordinate
ObjectCreate(“Headline” + TheTime + “s”, OBJ_TEXT, 0,
TheTime + VertRightLineShift, Height);

// Rotate the text 90 degrees
ObjectSet(“Headline” + TheTime + “s”, OBJPROP_ANGLE, 90);
ObjectSetText(“Headline” + TheTime + “s”, “News: ” + dispOCountry + ” ” + dispOTitle,
VertTxtSize, “Arial”, VertTxtColor);
}
} // end of “if shift)
} // end of (TheTime < ((Time[0]))+180+180)

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

return;
}

void OutputToChart()
{
// Added by Robert for using TxtSize and TxtColor for easier reading
int curY = 12;
int Days, Hours, Mins; // to display time in days, hours, minutes
string TimeStr;

if (ObjectFind(“Sponsor”) == -1)
ObjectCreate(“Sponsor”, OBJ_LABEL, 0, 0, 0);
ObjectSetText(“Sponsor”, commentStr, TxtSize, “Arial Bold”, TxtColorTitle);
ObjectSet(“Sponsor”, OBJPROP_CORNER, NewsCorner);
ObjectSet(“Sponsor”, OBJPROP_XDISTANCE, 10);
ObjectSet(“Sponsor”, OBJPROP_YDISTANCE, curY);

// 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 = dispMinutes[0];
if (dispMinutes[0] <= 0)
{
sinceUntil = “since “;
dispMins *= -1;
}
curY = curY + TxtSize + 4;

// 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 “;
}
}

if (ObjectFind(“Minutes”) == -1)
ObjectCreate(“Minutes”, OBJ_LABEL, 0, 0, 0);

if (dispMins == 999999)
ObjectSetText(“Minutes”, TimeStr, TxtSize, “Arial Bold”, TxtColorNews);
else
ObjectSetText(“Minutes”, TimeStr + sinceUntil + dispCountry[0] + “: ” + dispTitle[0], TxtSize, “Arial Bold”, TxtColorNews);

ObjectSet(“Minutes”, OBJPROP_CORNER, NewsCorner);
ObjectSet(“Minutes”, OBJPROP_XDISTANCE, 10);
ObjectSet(“Minutes”, OBJPROP_YDISTANCE, curY);

curY = curY + TxtSize + 4;
if (ObjectFind(“Impact”) == -1)
ObjectCreate(“Impact”, OBJ_LABEL, 0, 0, 0);
ObjectSetText(“Impact”, “Impact: ” + dispImpact[0], TxtSize, “Arial Bold”, TxtColorImpact);
ObjectSet(“Impact”, OBJPROP_CORNER, NewsCorner);
ObjectSet(“Impact”, OBJPROP_XDISTANCE, 10);
ObjectSet(“Impact”, OBJPROP_YDISTANCE, curY);

if (dispPrevious[0] != “”)
{
curY = curY + TxtSize + 4;
if (ObjectFind(“Previous”) == -1)
ObjectCreate(“Previous”, OBJ_LABEL, 0, 0, 0);
ObjectSetText(“Previous”, “Previous: ” + dispPrevious[0], TxtSize, “Arial Bold”, TxtColorPrevious);
ObjectSet(“Previous”, OBJPROP_CORNER, NewsCorner);
ObjectSet(“Previous”, OBJPROP_XDISTANCE, 10);
ObjectSet(“Previous”, OBJPROP_YDISTANCE, curY);
}

if (dispForecast[0] != “”)
{
curY = curY + TxtSize + 4;
if (ObjectFind(“Forecast”) == -1)
ObjectCreate(“Forecast”, OBJ_LABEL, 0, 0, 0);
ObjectSetText(“Forecast”, “Forecast: ” + dispForecast[0], TxtSize, “Arial Bold”, TxtColorForecast);
ObjectSet(“Forecast”, OBJPROP_CORNER, NewsCorner);
ObjectSet(“Forecast”, OBJPROP_XDISTANCE, 10);
ObjectSet(“Forecast”, OBJPROP_YDISTANCE, curY);
}

///////////////////////////////////////////////////////////////////////////
// Do second news event
if (ShowNextTwoEvents && dispTitle[1] != “”)
{
sinceUntil = “until “;
dispMins = dispMinutes[1];
if (dispMinutes[1] <= 0)
{
sinceUntil = “since “;
dispMins *= -1;
}

curY = curY + TxtSize + 20;

// 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 “;
}
}
if (ObjectFind(“Minutes2”) == -1)
ObjectCreate(“Minutes2”, OBJ_LABEL, 0, 0, 0);

if (dispMins == 999999)
ObjectSetText(“Minutes”, TimeStr, TxtSize, “Arial Bold”, TxtColorNews);
else
ObjectSetText(“Minutes2”, TimeStr + “until ” + dispCountry[1] + “: ” + dispTitle[1], TxtSize, “Arial Bold”, TxtColorNews);

ObjectSet(“Minutes2”, OBJPROP_CORNER, NewsCorner);
ObjectSet(“Minutes2”, OBJPROP_XDISTANCE, 10);
ObjectSet(“Minutes2”, OBJPROP_YDISTANCE, curY);

curY = curY + TxtSize + 4;
if (ObjectFind(“Impact2”) == -1)
ObjectCreate(“Impact2”, OBJ_LABEL, 0, 0, 0);
ObjectSetText(“Impact2”, “Impact: ” + dispImpact[1], TxtSize, “Arial Bold”, TxtColorImpact);
ObjectSet(“Impact2”, OBJPROP_CORNER, NewsCorner);
ObjectSet(“Impact2”, OBJPROP_XDISTANCE, 10);
ObjectSet(“Impact2”, OBJPROP_YDISTANCE, curY);

if (dispPrevious[1] != “”)
{
curY = curY + TxtSize + 4;
if (ObjectFind(“Previous2”) == -1)
ObjectCreate(“Previous2”, OBJ_LABEL, 0, 0, 0);
ObjectSetText(“Previous2”, “Previous: ” + dispPrevious[1], TxtSize, “Arial Bold”, TxtColorPrevious);
ObjectSet(“Previous2”, OBJPROP_CORNER, NewsCorner);
ObjectSet(“Previous2”, OBJPROP_XDISTANCE, 10);
ObjectSet(“Previous2”, OBJPROP_YDISTANCE, curY);
}

if (dispForecast[1] != “”)
{
curY = curY + TxtSize + 4;
if (ObjectFind(“Forecast2”) == -1)
ObjectCreate(“Forecast2”, OBJ_LABEL, 0, 0, 0);
ObjectSetText(“Forecast2”, “Forecast: ” + dispForecast[1], TxtSize, “Arial Bold”, TxtColorForecast);
ObjectSet(“Forecast2”, OBJPROP_CORNER, NewsCorner);
ObjectSet(“Forecast2”, OBJPROP_XDISTANCE, 10);
ObjectSet(“Forecast2”, OBJPROP_YDISTANCE, curY);
}
}

return;
}

double ImpactToNumber(string impact)
{
if (impact == “High”)
return (3);
if (impact == “Medium”)
return (2);
if (impact == “Low”)
return (1);
else
return (0);
}

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

string strMonth = StringSubstr(strDate, 0, 2);
string strDay = StringSubstr(strDate, 3, 2);
string strYear = StringSubstr(strDate, 6, 4);
// strYear = “20” + strYear;

int nTimeColonPos = StringFind(strTime, “:”);
string strHour = StringSubstr(strTime, 0, nTimeColonPos);
string strMinute = StringSubstr(strTime, nTimeColonPos+1, 2);
string strAM_PM = StringSubstr(strTime, StringLen(strTime)-2);

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

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

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

bool bWinInetDebug = false;

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

#import “wininet.dll”

#define INTERNET_FLAG_PRAGMA_NOCACHE 0x00000100 // Forces the request to be resolved by the origin server, even if a cached copy exists on the proxy.
#define INTERNET_FLAG_NO_CACHE_WRITE 0x04000000 // Does not add the returned entity to the cache.
#define INTERNET_FLAG_RELOAD 0x80000000 // Forces a download of the requested file, object, or directory listing from the origin server, not from the cache.

int InternetOpenW( string sAgent, int lAccessType, string sProxyName, string sProxyBypass, int lFlags );
int InternetOpenUrlW(int hInternetSession,string sUrl,string sHeaders=””,int lHeadersLength=0,int lFlags=0,int lContext=0);
int InternetReadFile(int hFile, uchar &sBuffer[],int lNumBytesToRead,int &lNumberOfBytesRead[]);
int InternetCloseHandle(int hInet);

#import

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

bool GrabWeb(string strUrl, string& strWebPage)
{
int hInternet;
int iResult;
int lReturn[] = {1};
uchar sBuffer[1024];
int bytes;
uint flags=INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD;

hInternet = InternetOpenUrlW(hSession(FALSE), strUrl, NULL, 0, flags);
//hInternet = InternetOpenUrlW(hSession(FALSE), strUrl, “0”, 0,
// INTERNET_FLAG_NO_CACHE_WRITE |
// INTERNET_FLAG_PRAGMA_NOCACHE |
// INTERNET_FLAG_RELOAD, 0);

if (bWinInetDebug)
Log(“hInternet: ” + hInternet);
if (hInternet == 0)
return(false);

Print(“Reading URL: ” + strUrl); //added by MN
iResult = InternetReadFile(hInternet, sBuffer, Buffer_LEN, lReturn);

if (bWinInetDebug) Log(“iResult: ” + iResult);
if (bWinInetDebug) Log(“lReturn: ” + lReturn[0]);
if (bWinInetDebug) Log(“iResult: ” + iResult);
if (bWinInetDebug) Log(“sBuffer: ” + CharArrayToString(sBuffer, 0, lReturn[0]));
if (iResult == 0) return(false);
bytes = lReturn[0];
strWebPage = CharArrayToString(sBuffer, 0, lReturn[0]);

//If there’s more data then keep reading it into the buffer
while (lReturn[0] != 0)
{
iResult = InternetReadFile(hInternet, sBuffer, Buffer_LEN, lReturn);
if (lReturn[0]==0) break;
bytes = bytes + lReturn[0];
strWebPage = strWebPage + CharArrayToString(sBuffer, 0, lReturn[0]);
}
Print(“Closing URL web connection”); //added by MN
iResult = InternetCloseHandle(hInternet);
if (iResult == 0) return(false);

return(true);
}

//=================================================================================================
//=================================================================================================
//=================================== LogUtils Functions ======================================
//=================================================================================================
//=================================================================================================

void OpenLog(string strName)
{
if (!EnableLogging)
return;

if (logHandle <= 0)
{
string strMonthPad = “”;
string strDayPad = “”;
if (Month() < 10)
strMonthPad = “0”;
if (Day() < 10)
strDayPad = “0”;

string strFilename = StringConcatenate(strName, “_”, Year(), strMonthPad, Month(), strDayPad, Day(), “_log.txt”);

logHandle = FileOpen(strFilename,FILE_CSV|FILE_READ|FILE_WRITE);
Print(“logHandle =================================== “, logHandle);
}
if (logHandle > 0)
{
FileFlush(logHandle);
FileSeek(logHandle, 0, SEEK_END);
}
}

void Log(string msg)
{
if (!EnableLogging)
return;

if (logHandle <= 0)
return;

msg = TimeToStr(TimeCurrent(),TIME_DATE|TIME_MINUTES|TIME_SECONDS) + ” ” + msg;
FileWrite(logHandle,msg);
}

//=================================================================================================
//=================================================================================================
//=================================== Timezone Functions ======================================
//=================================================================================================
//=================================================================================================

#import “kernel32.dll”
int GetTimeZoneInformation(int& TZInfoArray[]);
#import

#define TIME_ZONE_ID_UNKNOWN 0
#define TIME_ZONE_ID_STANDARD 1
#define TIME_ZONE_ID_DAYLIGHT 2

int TZInfoArray[43];

datetime myTimeGMT()
{
int DST = GetTimeZoneInformation(TZInfoArray);
if (DST == 1)
DST = 3600;
else
DST = 2;

return( TimeLocal() + DST + (OffsetHours * 3600) + (TZInfoArray[0] + TZInfoArray[42]) * 60 );
}

//=================================================================================================
//=================================================================================================
//================================= END IMPORTED FUNCTIONS =====================================
//=================================================================================================
//=================================================================================================

如果你对文件有了解,请帮助投票!

If you are familiar with the file, please help vote!

平均评分 0 / 5. 投票数: 0

到目前为止还没有投票!成为第一位投票人。

相关资源

暂无评论

暂无评论...
Ads Blocker Image Powered by Code Help Pro

检测到广告拦截程序!!!Ads Blocker Detected!!!

我们检测到您正在使用扩展来屏蔽广告。请通过禁用这些广告屏蔽程序或者把网站加入白名单来支持我们。

We have detected that you are using an extension to block advertisements. Please support us by disabling these advertising blocking programs or adding the website to the whitelist.