//+------------------------------------------------------------------+
//|                                                SecChartMaker.mq4 |
//|                                          Copyright (c) 2015, AUO |
//|                                     http://mt4indifx.seesaa.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright (c) 2015, AUO "
#property link      "http://mt4indifx.seesaa.net/"
#property version   "1.00"
#property strict

#property indicator_chart_window
 
#include <WinUser32.mqh>

#define FILE_VERSION 401
#define C_COPYRIGHT "(C)opyright 2003, MetaQuotes Software Corp."
#define CHART_CMD_UPDATE_DATA 33324

//--- input parameters
input string Name="";
input int IntervalSec=10;
input int OmitDigit=0;

//--- indicator buffers

//---
string gs_symbol;
int gi_filehandle=INVALID_HANDLE;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {
   bool lb_symbol;
   long ll_chart;
   string ls_suffix="";
   
   //---
   ll_chart=ChartFirst();
   lb_symbol=false;
   while(ll_chart>0) {
      if(Name==ChartSymbol(ll_chart)) lb_symbol=true;
      ll_chart=ChartNext(ll_chart);
   }
   
   if(Name=="" || lb_symbol) {
      ls_suffix=StringConcatenate("_",IntegerToString(IntervalSec),"S");
      if(OmitDigit!=0) ls_suffix=StringConcatenate(ls_suffix,"o",IntegerToString(OmitDigit));
      gs_symbol=StringConcatenate(StringSubstr(Symbol(),0,6),ls_suffix);
      if(StringLen(gs_symbol)>11) {
         gs_symbol=StringSubstr(gs_symbol,0,11-StringLen(ls_suffix))+ls_suffix;
      }
   } else {
      gs_symbol=Name;
      if(StringLen(gs_symbol)>11) {
         gs_symbol=StringSubstr(gs_symbol,0,11);
      }
   }
   
   //--- file open
   gi_filehandle=OpenHistoryFile(gs_symbol,PERIOD_M1);
   if(gi_filehandle==INVALID_HANDLE) return(INIT_FAILED);
   //--- write history file header
   WriteHistoryHeader(gi_filehandle,gs_symbol,PERIOD_M1);
   //--- indicator buffers mapping
   //--- name for DataWindow and indicator subwindow label
   //---
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
   //---
   CloseHistoryFile(gi_filehandle);
   //---
   return;
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]) {
   //---
   MqlRates ls_rate={0,0,0,0,0,0,0};
   
   //--- counting from 0 to rates_total
   
   //----
   ls_rate.time=TimeCurrent();
   ls_rate.open=NormalizeDouble(Bid,Digits-OmitDigit);
   ls_rate.high=NormalizeDouble(Bid,Digits-OmitDigit);
   ls_rate.low=NormalizeDouble(Bid,Digits-OmitDigit);
   ls_rate.close=NormalizeDouble(Bid,Digits-OmitDigit);
   ls_rate.tick_volume=1;
   WriteHistoryData(gi_filehandle,IntervalSec,ls_rate,false,true);
   UpdateChartWindow(gs_symbol,PERIOD_M1);
   //--- return value of prev_calculated for next call
   return(rates_total);
}

//+------------------------------------------------------------------+
//| Subroutine                                                       |
//+------------------------------------------------------------------+
int OpenHistoryFile(string symbol,int timeframe) {
   int li_handle;
   
   li_handle=FileOpenHistory(symbol+IntegerToString(timeframe)+".hst",FILE_BIN|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_ANSI);
   return(li_handle);
}
//+------------------------------------------------------------------+
void WriteHistoryHeader(int filehandle,string symbol,int timeframe) {
   int li_unused[13];
   
   if(filehandle==INVALID_HANDLE) return;
   ArrayInitialize(li_unused,0);
   FileWriteInteger(filehandle,FILE_VERSION,LONG_VALUE);
   FileWriteString(filehandle,C_COPYRIGHT,64);
   FileWriteString(filehandle,symbol,12);
   FileWriteInteger(filehandle,timeframe,LONG_VALUE);
   FileWriteInteger(filehandle,Digits,LONG_VALUE);
   FileWriteInteger(filehandle,0,LONG_VALUE);
   FileWriteInteger(filehandle,0,LONG_VALUE);
   FileWriteArray(filehandle,li_unused,0,13);
   return;
}
//+------------------------------------------------------------------+
void WriteHistoryData(int filehandle,int second,const MqlRates& rate,bool minusvolume,bool flush) {
   static MqlRates written={0,0,0,0,0,0,0,0};
   static ulong fp=0;
   
   if(filehandle==INVALID_HANDLE) return;
   if(fp==0 || written.time+second<=rate.time) {
      //--- new
      written=rate;
      written.time=rate.time/second;
      written.time*=second;
      written.spread=0;
      written.real_volume=0;
      fp=FileTell(filehandle);
      FileWriteStruct(filehandle,written);
      if(minusvolume) written.tick_volume-=rate.tick_volume;
      if(flush) FileFlush(filehandle);
   } else if(written.time<=rate.time && rate.time<written.time+second) {
      //--- current
      if(written.high<rate.high) written.high=rate.high;
      if(written.low>rate.low) written.low=rate.low;
      written.close=rate.close;
      written.tick_volume+=rate.tick_volume;
      FileSeek(filehandle,fp,SEEK_SET);
      FileWriteStruct(filehandle,written);
      if(minusvolume) written.tick_volume-=rate.tick_volume;
      if(flush) FileFlush(filehandle);
   }
   return;
}
//+------------------------------------------------------------------+
int UpdateChartWindow(string symbol,int timeframe) {
   static int si_hwnd=0;
   
   if(si_hwnd==0) {
      si_hwnd=WindowHandle(symbol,timeframe);
      if(si_hwnd!=0) Print("Chart window detected");
   }
   if(si_hwnd!=0) {
      if(!IsDllsAllowed()) {
         //--- DLL calls must be allowd
         Print("[Allow DLL imports] not checked");
         return(-1);
      }
      if(PostMessageA(si_hwnd,WM_COMMAND,CHART_CMD_UPDATE_DATA,0)==0) {
         //PostMessage failed, chart window closed
         si_hwnd=0;
         return(-1);
      } else {
         //PostMessage succeed
         return(0);
      }
   }
   //window not found or PostMessage failed
   return(-1);
}
//+------------------------------------------------------------------+
void CloseHistoryFile(int filehandle) {
   if(filehandle!=INVALID_HANDLE) {
      FileClose(filehandle);
      filehandle=INVALID_HANDLE;
   }
   return;
}
//+------------------------------------------------------------------+