MT5APIFormat.h 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. //+------------------------------------------------------------------+
  2. //| MetaTrader 5 API |
  3. //| Copyright 2000-2019, MetaQuotes Software Corp. |
  4. //| http://www.metaquotes.net |
  5. //+------------------------------------------------------------------+
  6. #pragma once
  7. #include <time.h>
  8. #include "MT5APIStr.h"
  9. #include "MT5APIMath.h"
  10. #include "MT5APITime.h"
  11. #include "..\Bases\MT5APITick.h"
  12. #include "..\Bases\MT5APIOrder.h"
  13. #include "..\Bases\MT5APIDeal.h"
  14. #include "..\Bases\MT5APIPosition.h"
  15. //+------------------------------------------------------------------+
  16. //| Format strings |
  17. //+------------------------------------------------------------------+
  18. class SMTFormat
  19. {
  20. private:
  21. //--- constants
  22. enum constants
  23. {
  24. SIG_DECIMAL =L'.',
  25. SIG_NEGATIVE =L'-',
  26. SIG_THOUSAND =L' ',
  27. VOLUME_K =L'K',
  28. VOLUME_M =L'M',
  29. };
  30. public:
  31. //--- error
  32. static LPCWSTR FormatError(const MTAPIRES retcode);
  33. //--- double to string
  34. static LPCWSTR FormatDouble(CMTStr &str,double val,UINT digits);
  35. static LPCWSTR FormatMoney(CMTStr &str,double val,UINT digits);
  36. //--- price to string
  37. static LPCWSTR FormatPrice(CMTStr &str,double val,UINT digits,UINT extra_digits=0);
  38. static LPCWSTR FormatPrices(CMTStr &str,MTTickShort& tick,const UINT digits);
  39. //--- volume & size
  40. static LPCWSTR FormatVolumeDouble(CMTStr &str,const double volume,const bool compact);
  41. static LPCWSTR FormatVolume(CMTStr &str,const UINT64 volume,const bool compact=true);
  42. static LPCWSTR FormatVolumeExt(CMTStr &str,const UINT64 volume,const bool compact=true);
  43. static LPCWSTR FormatVolumeOrder(CMTStr &str,const UINT64 volume_initial,const UINT64 volume_current);
  44. static LPCWSTR FormatVolumeExtOrder(CMTStr &str,const UINT64 volume_initial,const UINT64 volume_current);
  45. static LPCWSTR FormatSize(CMTStr &str,const double size,const bool compact=true);
  46. static LPCWSTR FormatSizeOrder(CMTStr &str,const double size_initial,const double size_current);
  47. //--- date & time
  48. static LPCWSTR FormatDateTime(CMTStr &str,const SYSTEMTIME &st,bool useTime=true,bool useSec=false);
  49. static LPCWSTR FormatDateTime(CMTStr &str,INT64 ctm,bool useTime=true,bool useSec=false);
  50. static LPCWSTR FormatDateTimeMsc(CMTStr &str,const SYSTEMTIME &st,bool useTime=true,bool useSec=false);
  51. static LPCWSTR FormatDateTimeMsc(CMTStr &str,INT64 ctm,bool useTime=true,bool useSec=false);
  52. static LPCWSTR FormatTime(CMTStr &str,INT64 ctm,bool useSec=false);
  53. static LPCWSTR FormatTimeMsc(CMTStr &str,INT64 ctm,bool useSec=false);
  54. //--- IP & port
  55. static LPCWSTR FormatIP(CMTStr &str,const UINT ip,const UINT port=0);
  56. static LPCWSTR FormatIP(CMTStr &str,const USHORT* ip,const UINT port=0);
  57. //--- positions
  58. static LPCWSTR FormatPositionType(CMTStr &str,const UINT type);
  59. //--- orders
  60. static LPCWSTR FormatOrderType(CMTStr &str,const UINT type);
  61. static LPCWSTR FormatOrderStatus(CMTStr &str,const UINT status);
  62. static LPCWSTR FormatOrderTypeFilling(CMTStr &str,const UINT type);
  63. static LPCWSTR FormatOrderTypeTime(CMTStr &str,const UINT type);
  64. static LPCWSTR FormatOrderTypeReason(CMTStr &str,UINT reason);
  65. static LPCWSTR FormatOrderPrice(CMTStr &str,const double price_order,const double price_trigger,const UINT digits);
  66. //--- deals
  67. static LPCWSTR FormatDealAction(CMTStr &str,const UINT action);
  68. static LPCWSTR FormatDealEntry(CMTStr &str,const UINT entry);
  69. //---
  70. static LPCWSTR FormatModifyFlags(CMTStr &str,const UINT modify_flags);
  71. private:
  72. //--- UINT64 to string
  73. static LPCWSTR FormatDouble(CMTStr &str,UINT64 val,UINT digits);
  74. static LPCWSTR FormatDoubleBrief(CMTStr &str,UINT64 val,UINT digits);
  75. static LPCWSTR FormatMoney(CMTStr &str,UINT64 val,UINT digits);
  76. //--- trim zero
  77. static void TrimZeros(CMTStr &str,UINT extra_digits=UINT_MAX);
  78. };
  79. //+------------------------------------------------------------------+
  80. //| Retcode description |
  81. //+------------------------------------------------------------------+
  82. inline LPCWSTR SMTFormat::FormatError(const MTAPIRES retcode)
  83. {
  84. //--- error description
  85. struct ErrorDesc
  86. {
  87. MTAPIRES code;
  88. LPCWSTR desc;
  89. };
  90. //--- errors
  91. static ErrorDesc errors[]=
  92. {
  93. { MT_RET_OK, L"Done" },
  94. { MT_RET_OK_NONE, L"OK/None" },
  95. { MT_RET_ERROR, L"Common error" },
  96. { MT_RET_ERR_PARAMS, L"Invalid parameters" },
  97. { MT_RET_ERR_DATA, L"Invalid data" },
  98. { MT_RET_ERR_DISK, L"Disk error" },
  99. { MT_RET_ERR_MEM, L"Memory error" },
  100. { MT_RET_ERR_NETWORK, L"Network error" },
  101. { MT_RET_ERR_PERMISSIONS, L"Not enough permissions" },
  102. { MT_RET_ERR_TIMEOUT, L"Operation timeout" },
  103. { MT_RET_ERR_CONNECTION, L"No connection" },
  104. { MT_RET_ERR_NOSERVICE, L"Service is not available" },
  105. { MT_RET_ERR_FREQUENT, L"Too frequent requests" },
  106. { MT_RET_ERR_NOTFOUND, L"Not found" },
  107. { MT_RET_ERR_SHUTDOWN, L"Server shutdown in progress" },
  108. { MT_RET_ERR_CANCEL, L"Operation was canceled" },
  109. { MT_RET_ERR_DUPLICATE, L"Duplicate attempt" },
  110. //--- auth errors
  111. { MT_RET_AUTH_CLIENT_INVALID, L"Invalid terminal type" },
  112. { MT_RET_AUTH_ACCOUNT_INVALID, L"Invalid account" },
  113. { MT_RET_AUTH_ACCOUNT_DISABLED, L"Account disabled" },
  114. { MT_RET_AUTH_ADVANCED, L"Advanced authorization" },
  115. { MT_RET_AUTH_CERTIFICATE, L"Certificate required" },
  116. { MT_RET_AUTH_CERTIFICATE_BAD, L"Invalid certificate" },
  117. { MT_RET_AUTH_NOTCONFIRMED, L"Certificate is not confirmed" },
  118. { MT_RET_AUTH_SERVER_INTERNAL, L"Attempt to connect to non-access server" },
  119. { MT_RET_AUTH_SERVER_BAD, L"Invalid or fake server" },
  120. { MT_RET_AUTH_UPDATE_ONLY, L"Only updates available" },
  121. { MT_RET_AUTH_CLIENT_OLD, L"Old version" },
  122. { MT_RET_AUTH_MANAGER_NOCONFIG, L"Account doesn't have manager config" },
  123. { MT_RET_AUTH_MANAGER_IPBLOCK, L"IP address unallowed for manager" },
  124. { MT_RET_AUTH_GROUP_INVALID, L"Group is not initialized, server restart needed" },
  125. { MT_RET_AUTH_CA_DISABLED, L"Certificate generation disabled" },
  126. { MT_RET_AUTH_INVALID_ID, L"Invalid or disabled server id [check server id]"},
  127. { MT_RET_AUTH_INVALID_IP, L"Unallowed address [check server ip address]" },
  128. { MT_RET_AUTH_INVALID_TYPE, L"Invalid server type [check server id and type]" },
  129. { MT_RET_AUTH_SERVER_BUSY, L"Server is busy" },
  130. { MT_RET_AUTH_SERVER_CERT, L"Invalid server certificate or invalid local time" },
  131. { MT_RET_AUTH_ACCOUNT_UNKNOWN, L"Unknown account" },
  132. { MT_RET_AUTH_SERVER_OLD, L"Old server version" },
  133. { MT_RET_AUTH_SERVER_LIMIT, L"Server cannot be connected due to license limitation" },
  134. { MT_RET_AUTH_MOBILE_DISABLED, L"Mobile terminal isn't allowed in license" },
  135. { MT_RET_AUTH_MANAGER_TYPE, L"Connection type is not permitted for manager" },
  136. { MT_RET_AUTH_DEMO_DISABLED, L"Demo allocation disabled" },
  137. { MT_RET_AUTH_RESET_PASSWORD, L"Master password must be changed" },
  138. //--- config errors
  139. { MT_RET_CFG_LAST_ADMIN, L"Last admin config cannot be deleted" },
  140. { MT_RET_CFG_LAST_ADMIN_GROUP, L"Last admin group cannot be deleted" },
  141. { MT_RET_CFG_NOT_EMPTY, L"Accounts or trades in group/symbol" },
  142. { MT_RET_CFG_INVALID_RANGE, L"Invalid account or trade ranges"},
  143. { MT_RET_CFG_NOT_MANAGER_LOGIN, L"Account doesn't belong to manager group"},
  144. { MT_RET_CFG_BUILTIN, L"Built-in protected config" },
  145. { MT_RET_CFG_DUPLICATE, L"Configuration duplicate" },
  146. { MT_RET_CFG_LIMIT_REACHED, L"Configuration limit reached" },
  147. { MT_RET_CFG_NO_ACCESS_TO_MAIN, L"Invalid network configuration" },
  148. { MT_RET_CFG_DEALER_ID_EXIST, L"Dealer with same ID already exists" },
  149. { MT_RET_CFG_BIND_ADDR_EXIST, L"Binding address already exists" },
  150. { MT_RET_CFG_WORKING_TRADE, L"Attempt to delete working trade server" },
  151. { MT_RET_CFG_GATEWAY_NAME_EXIST,L"Gateway with same name already exists" },
  152. { MT_RET_CFG_SWITCH_TO_BACKUP, L"Server must be switched to backup mode" },
  153. { MT_RET_CFG_NO_BACKUP_MODULE, L"Backup server module is absent" },
  154. { MT_RET_CFG_NO_TRADE_MODULE, L"Trade server module is absent" },
  155. { MT_RET_CFG_NO_HISTORY_MODULE, L"History server module is absent" },
  156. { MT_RET_CFG_ANOTHER_SWITCH, L"Another switching process in progress" },
  157. { MT_RET_CFG_NO_LICENSE_FILE, L"License file is absent" },
  158. { MT_RET_CFG_GATEWAY_LOGIN_EXIST,L"Gateway with same login already exist" },
  159. //--- client errors
  160. { MT_RET_USR_LAST_ADMIN, L"Last admin account cannot be deleted" },
  161. { MT_RET_USR_LOGIN_EXHAUSTED, L"Login range exhausted" },
  162. { MT_RET_USR_LOGIN_PROHIBITED, L"Login reserved at another server" },
  163. { MT_RET_USR_LOGIN_EXIST, L"Account already exists" },
  164. { MT_RET_USR_SUICIDE, L"Attempt of self-deletion" },
  165. { MT_RET_USR_INVALID_PASSWORD, L"Invalid account password" },
  166. { MT_RET_USR_LIMIT_REACHED, L"User limit reached" },
  167. { MT_RET_USR_HAS_TRADES, L"Account has open trades" },
  168. { MT_RET_USR_DIFFERENT_SERVERS, L"Attempt to move account to different server" },
  169. { MT_RET_USR_DIFFERENT_CURRENCY,L"Attempt to move account to group with different currency" },
  170. { MT_RET_USR_IMPORT_BALANCE, L"Account balance import error" },
  171. { MT_RET_USR_IMPORT_GROUP, L"Imported account has invalid group"},
  172. { MT_RET_USR_ACCOUNT_EXIST, L"Account already exist" },
  173. //--- trade errors
  174. { MT_RET_TRADE_LIMIT_REACHED, L"Order or deal limit reached" },
  175. { MT_RET_TRADE_ORDER_EXIST, L"Order already exists" },
  176. { MT_RET_TRADE_ORDER_EXHAUSTED, L"Order range exhausted" },
  177. { MT_RET_TRADE_DEAL_EXHAUSTED, L"Deal range exhausted" },
  178. { MT_RET_TRADE_MAX_MONEY, L"Money limit reached" },
  179. { MT_RET_TRADE_DEAL_EXIST, L"Deal already exists" },
  180. { MT_RET_TRADE_ORDER_PROHIBITED,L"Order ticket reserved at another server" },
  181. { MT_RET_TRADE_DEAL_PROHIBITED, L"Deal ticket reserved at another server" },
  182. //--- report errors
  183. { MT_RET_REPORT_SNAPSHOT, L"Base snapshot error" },
  184. { MT_RET_REPORT_NOTSUPPORTED, L"Method is not supported by this report" },
  185. { MT_RET_REPORT_NODATA, L"No data for report" },
  186. { MT_RET_REPORT_TEMPLATE_BAD, L"Bad template" },
  187. { MT_RET_REPORT_TEMPLATE_END, L"End of template" },
  188. { MT_RET_REPORT_INVALID_ROW, L"Invalid row size" },
  189. { MT_RET_REPORT_LIMIT_REPEAT, L"Tag repeat limit reached " },
  190. { MT_RET_REPORT_LIMIT_REPORT, L"Report size limit reached" },
  191. //--- history errors
  192. { MT_RET_HST_SYMBOL_NOTFOUND, L"Symbol not found, try to restart history server" },
  193. //--- request errors
  194. { MT_RET_REQUEST_INWAY, L"Request on the way" },
  195. { MT_RET_REQUEST_ACCEPTED, L"Request accepted" },
  196. { MT_RET_REQUEST_PROCESS, L"Request processed" },
  197. { MT_RET_REQUEST_REQUOTE, L"Requote" },
  198. { MT_RET_REQUEST_PRICES, L"Prices" },
  199. { MT_RET_REQUEST_REJECT, L"Request rejected" },
  200. { MT_RET_REQUEST_CANCEL, L"Request canceled" },
  201. { MT_RET_REQUEST_PLACED, L"Order placed" },
  202. { MT_RET_REQUEST_DONE, L"Request executed" },
  203. { MT_RET_REQUEST_DONE_PARTIAL, L"Request executed partially" },
  204. { MT_RET_REQUEST_ERROR, L"Request error" },
  205. { MT_RET_REQUEST_TIMEOUT, L"Request timeout" },
  206. { MT_RET_REQUEST_INVALID, L"Invalid request" },
  207. { MT_RET_REQUEST_INVALID_VOLUME,L"Invalid volume" },
  208. { MT_RET_REQUEST_INVALID_PRICE, L"Invalid price" },
  209. { MT_RET_REQUEST_INVALID_STOPS, L"Invalid stops" },
  210. { MT_RET_REQUEST_TRADE_DISABLED,L"Trade disabled" },
  211. { MT_RET_REQUEST_MARKET_CLOSED, L"Market closed" },
  212. { MT_RET_REQUEST_NO_MONEY, L"No money" },
  213. { MT_RET_REQUEST_PRICE_CHANGED, L"Price changed" },
  214. { MT_RET_REQUEST_PRICE_OFF, L"No prices" },
  215. { MT_RET_REQUEST_INVALID_EXP, L"Invalid expiration" },
  216. { MT_RET_REQUEST_ORDER_CHANGED, L"Order has been changed already" },
  217. { MT_RET_REQUEST_TOO_MANY, L"Too many trade requests" },
  218. { MT_RET_REQUEST_AT_DISABLED_SERVER, L"AutoTrading disabled by server" },
  219. { MT_RET_REQUEST_AT_DISABLED_CLIENT, L"AutoTrading disabled by client" },
  220. { MT_RET_REQUEST_LOCKED, L"Order locked by dealer" },
  221. { MT_RET_REQUEST_FROZEN, L"Modification failed due to order or position being close to market" },
  222. { MT_RET_REQUEST_INVALID_FILL, L"Unsupported filling mode" },
  223. { MT_RET_REQUEST_RETURN, L"Request returned in queue" },
  224. { MT_RET_REQUEST_DONE_CANCEL, L"Request executed partially" },
  225. { MT_RET_REQUEST_ONLY_REAL, L"Allowed for real accounts only" },
  226. { MT_RET_REQUEST_LIMIT_ORDERS, L"Order limit reached" },
  227. { MT_RET_REQUEST_LIMIT_VOLUME, L"Volume limit reached" },
  228. { MT_RET_REQUEST_POSITION_CLOSED, L"Position already closed" },
  229. { MT_RET_REQUEST_EXECUTION_SKIPPED, L"Execution doesn't belong to this server" },
  230. { MT_RET_REQUEST_INVALID_CLOSE_VOLUME, L"Volume to be closed exceeds the position volume" },
  231. { MT_RET_REQUEST_CLOSE_ORDER_EXIST, L"Order to close this position already exists" },
  232. { MT_RET_REQUEST_REQUOTE_RETURN, L"Requote" },
  233. { MT_RET_REQUEST_LIMIT_POSITIONS, L"Position limit reached" },
  234. { MT_RET_REQUEST_REJECT_CANCEL, L"Request rejected, order will be canceled"},
  235. { MT_RET_REQUEST_LONG_ONLY, L"Only long positions are allowed" },
  236. { MT_RET_REQUEST_SHORT_ONLY, L"Only short positions are allowed" },
  237. { MT_RET_REQUEST_CLOSE_ONLY, L"Only position closing is allowed" },
  238. //--- API retcodes
  239. { MT_RET_ERR_NOTIMPLEMENT, L"Not implemented" },
  240. { MT_RET_ERR_NOTMAIN, L"Operation must be performed on main server"},
  241. { MT_RET_ERR_NOTSUPPORTED, L"Command doesn't supported" },
  242. { MT_RET_ERR_DEADLOCK, L"Operation canceled due possible deadlock" },
  243. { MT_RET_ERR_LOCKED, L"Operation on locked entity" },
  244. //--- default
  245. { INT_MAX, L"Network problem" },
  246. };
  247. //--- search description
  248. for(UINT i=0;i<_countof(errors);i++)
  249. if(errors[i].code==retcode) return(errors[i].desc);
  250. //--- default value
  251. return(L"Unknown error");
  252. }
  253. //+------------------------------------------------------------------+
  254. //| Format double value |
  255. //+------------------------------------------------------------------+
  256. inline LPCWSTR SMTFormat::FormatDouble(CMTStr &str,double val,UINT digits)
  257. {
  258. double valdec;
  259. UINT digits_int=(digits<10)?digits:10;
  260. //--- convert to integer
  261. valdec=val*SMTMath::DecPow((int)digits_int);
  262. //--- check size
  263. if(valdec>=double(_I64_MAX/100i64) || valdec<=double(_I64_MIN/100i64))
  264. {
  265. CMTStr32 fmt;
  266. int pos;
  267. //--- format using CRT
  268. fmt.Format(L"%%.0%ulf",digits_int);
  269. str.Format(fmt.Str(),val);
  270. //--- decimal point
  271. pos=str.FindRChar(L'.');
  272. if(pos>=0) str.Buffer()[pos]=SIG_DECIMAL;
  273. //---
  274. return(str.Str());
  275. }
  276. //--- format fast
  277. if(val>=0)
  278. FormatDouble(str,UINT64(valdec+0.5),digits_int);
  279. else
  280. {
  281. FormatDouble(str,UINT64(0.5-valdec),digits_int);
  282. str.Insert(0,SIG_NEGATIVE);
  283. }
  284. //---
  285. return(str.Str());
  286. }
  287. //+------------------------------------------------------------------+
  288. //| Format money |
  289. //+------------------------------------------------------------------+
  290. inline LPCWSTR SMTFormat::FormatMoney(CMTStr &str,double val,UINT digits)
  291. {
  292. double valdec;
  293. //--- convert to integer
  294. valdec=val*SMTMath::DecPow((int)digits);
  295. //--- check size
  296. if(valdec>=double(_I64_MAX/100i64) || valdec<=double(_I64_MIN/100i64))
  297. {
  298. CMTStr32 fmt;
  299. int pos;
  300. //--- format using CRT
  301. fmt.Format(L"%%.0%ulf",digits);
  302. str.Format(fmt.Str(),val);
  303. //--- decimal point
  304. pos=str.FindRChar(L'.');
  305. if(pos>=0) str.Buffer()[pos]=SIG_DECIMAL;
  306. //--- insert thousands delimeters
  307. for(pos=str.FindRChar(L'.')-3;pos>=3;pos-=3)
  308. str.Insert((UINT)pos,SIG_THOUSAND);
  309. //---
  310. return(str.Str());
  311. }
  312. //--- format fast
  313. if(val>=0)
  314. FormatMoney(str,UINT64(valdec+0.5),digits);
  315. else
  316. {
  317. FormatMoney(str,UINT64(0.5-valdec),digits);
  318. str.Insert(0,SIG_NEGATIVE);
  319. }
  320. //---
  321. return(str.Str());
  322. }
  323. //+------------------------------------------------------------------+
  324. //| Format price |
  325. //+------------------------------------------------------------------+
  326. inline LPCWSTR SMTFormat::FormatPrice(CMTStr &str,double val,UINT digits,UINT extra_digits)
  327. {
  328. //--- format with extra digits
  329. FormatDouble(str,val,digits+extra_digits);
  330. //--- trim zero
  331. TrimZeros(str,extra_digits);
  332. //--- return
  333. return(str.Str());
  334. }
  335. //+------------------------------------------------------------------+
  336. //| Current prices |
  337. //+------------------------------------------------------------------+
  338. inline LPCWSTR SMTFormat::FormatPrices(CMTStr &str,MTTickShort& tick,const UINT digits)
  339. {
  340. CMTStr32 sbid,sask,slast;
  341. //--- check last prices
  342. if(!tick.last) str.Format(L"%s / %s" ,FormatPrice(sbid,tick.bid,digits),FormatPrice(sask,tick.ask,digits));
  343. else str.Format(L"%s / %s / %s",FormatPrice(sbid,tick.bid,digits),FormatPrice(sask,tick.ask,digits),FormatPrice(slast,tick.last,digits));
  344. //--- return
  345. return(str.Str());
  346. }
  347. //+------------------------------------------------------------------+
  348. //| Format trade volume |
  349. //+------------------------------------------------------------------+
  350. inline LPCWSTR SMTFormat::FormatVolumeDouble(CMTStr &str,const double volume,const bool compact/*=true*/)
  351. {
  352. //--- check M
  353. if(compact && volume>1000000.0)
  354. {
  355. //---
  356. str.Format(L"%.8lf",volume/1000000.0);
  357. TrimZeros(str,8);
  358. str.Append(VOLUME_M);
  359. //---
  360. return(str.Str());
  361. }
  362. //--- check K
  363. if(compact && volume>1000.0)
  364. {
  365. //---
  366. str.Format(L"%.5lf",volume/1000.0);
  367. TrimZeros(str,5);
  368. str.Append(VOLUME_K);
  369. //---
  370. return(str.Str());
  371. }
  372. //--- normal method
  373. FormatDouble(str,volume,MTAPI_VOLUME_EXT_DIGITS);
  374. TrimZeros(str,6);
  375. return(str.Str());
  376. }
  377. //+------------------------------------------------------------------+
  378. //| Format trade volume |
  379. //+------------------------------------------------------------------+
  380. inline LPCWSTR SMTFormat::FormatVolume(CMTStr &str,const UINT64 volume,const bool compact/*=true*/)
  381. {
  382. return(FormatVolumeDouble(str,SMTMath::VolumeToDouble(volume),compact));
  383. }
  384. //+------------------------------------------------------------------+
  385. //| Format trade volume |
  386. //+------------------------------------------------------------------+
  387. inline LPCWSTR SMTFormat::FormatVolumeExt(CMTStr &str,const UINT64 volume,const bool compact/*=true*/)
  388. {
  389. return(FormatVolumeDouble(str,SMTMath::VolumeExtToDouble(volume),compact));
  390. }
  391. //+------------------------------------------------------------------+
  392. //| Format order volume |
  393. //+------------------------------------------------------------------+
  394. inline LPCWSTR SMTFormat::FormatVolumeOrder(CMTStr &str,const UINT64 volume_initial,const UINT64 volume_current)
  395. {
  396. CMTStr64 vol_filled,vol_init;
  397. //---
  398. str.Format(L"%s / %s",FormatVolume(vol_init,volume_initial),
  399. FormatVolume(vol_filled,volume_initial-volume_current));
  400. //--- summary
  401. return(str.Str());
  402. }
  403. //+------------------------------------------------------------------+
  404. //| Format order volume |
  405. //+------------------------------------------------------------------+
  406. inline LPCWSTR SMTFormat::FormatVolumeExtOrder(CMTStr &str,const UINT64 volume_initial,const UINT64 volume_current)
  407. {
  408. CMTStr64 vol_filled,vol_init;
  409. //---
  410. str.Format(L"%s / %s",FormatVolumeExt(vol_init,volume_initial),
  411. FormatVolumeExt(vol_filled,volume_initial-volume_current));
  412. //--- summary
  413. return(str.Str());
  414. }
  415. //+------------------------------------------------------------------+
  416. //| Format trade amount |
  417. //+------------------------------------------------------------------+
  418. inline LPCWSTR SMTFormat::FormatSize(CMTStr &str,const double volume,const bool compact/*=true*/)
  419. {
  420. return(FormatVolumeDouble(str,volume,compact));
  421. }
  422. //+------------------------------------------------------------------+
  423. //| Format order amount |
  424. //+------------------------------------------------------------------+
  425. inline LPCWSTR SMTFormat::FormatSizeOrder(CMTStr &str,const double size_initial,const double size_current)
  426. {
  427. CMTStr64 sz_filled,sz_current;
  428. //---
  429. str.Format(L"%s / %s",FormatSize(sz_filled,size_initial),
  430. FormatSize(sz_current,size_initial-size_current));
  431. //---
  432. return(str.Str());
  433. }
  434. //+------------------------------------------------------------------+
  435. //| Format date & time |
  436. //+------------------------------------------------------------------+
  437. inline LPCWSTR SMTFormat::FormatDateTime(CMTStr &str,const SYSTEMTIME &st,bool useTime/*=true*/,bool useSec/*=false*/)
  438. {
  439. //---
  440. if(useTime)
  441. {
  442. if(useSec)
  443. str.Format(L"%04d.%02d.%02d %02d:%02d:%02d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);
  444. else
  445. str.Format(L"%04d.%02d.%02d %02d:%02d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute);
  446. }
  447. else str.Format(L"%04d.%02d.%02d",st.wYear,st.wMonth,st.wDay);
  448. //---
  449. return(str.Str());
  450. }
  451. //+------------------------------------------------------------------+
  452. //| Format date & time |
  453. //+------------------------------------------------------------------+
  454. inline LPCWSTR SMTFormat::FormatDateTime(CMTStr &str,INT64 ctm,bool useTime/*=true*/,bool useSec/*=false*/)
  455. {
  456. tm ttm={};
  457. //---
  458. if(!SMTTime::ParseTime(ctm,&ttm)) return(str.Str());
  459. //---
  460. if(useTime)
  461. {
  462. if(useSec)
  463. str.Format(L"%04d.%02d.%02d %02d:%02d:%02d",ttm.tm_year+1900,ttm.tm_mon+1,ttm.tm_mday,ttm.tm_hour,ttm.tm_min,ttm.tm_sec);
  464. else
  465. str.Format(L"%04d.%02d.%02d %02d:%02d",ttm.tm_year+1900,ttm.tm_mon+1,ttm.tm_mday,ttm.tm_hour,ttm.tm_min);
  466. }
  467. else str.Format(L"%04d.%02d.%02d",ttm.tm_year+1900,ttm.tm_mon+1,ttm.tm_mday);
  468. //---
  469. return(str.Str());
  470. }
  471. //+------------------------------------------------------------------+
  472. //| Format date & time |
  473. //+------------------------------------------------------------------+
  474. inline LPCWSTR SMTFormat::FormatDateTimeMsc(CMTStr &str,const SYSTEMTIME &st,bool useTime/*=true*/,bool useSec/*=false*/)
  475. {
  476. //---
  477. if(useTime)
  478. {
  479. if(useSec)
  480. str.Format(L"%04d.%02d.%02d %02d:%02d:%02d.%03u",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
  481. else
  482. str.Format(L"%04d.%02d.%02d %02d:%02d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute);
  483. }
  484. else str.Format(L"%04d.%02d.%02d",st.wYear,st.wMonth,st.wDay);
  485. //---
  486. return(str.Str());
  487. }
  488. //+------------------------------------------------------------------+
  489. //| Format date & time |
  490. //+------------------------------------------------------------------+
  491. inline LPCWSTR SMTFormat::FormatDateTimeMsc(CMTStr &str,INT64 ctm,bool useTime/*=true*/,bool useSec/*=false*/)
  492. {
  493. tm ttm={};
  494. //---
  495. if(!SMTTime::ParseTime(ctm/1000,&ttm))
  496. return(str.Str());
  497. //---
  498. if(useTime)
  499. {
  500. if(useSec)
  501. str.Format(L"%04d.%02d.%02d %02d:%02d:%02d.%03d",ttm.tm_year+1900,ttm.tm_mon+1,ttm.tm_mday,ttm.tm_hour,ttm.tm_min,ttm.tm_sec,(int)(ctm%1000));
  502. else
  503. str.Format(L"%04d.%02d.%02d %02d:%02d",ttm.tm_year+1900,ttm.tm_mon+1,ttm.tm_mday,ttm.tm_hour,ttm.tm_min);
  504. }
  505. else str.Format(L"%04d.%02d.%02d",ttm.tm_year+1900,ttm.tm_mon+1,ttm.tm_mday);
  506. //---
  507. return(str.Str());
  508. }
  509. //+------------------------------------------------------------------+
  510. //| Format time |
  511. //+------------------------------------------------------------------+
  512. inline LPCWSTR SMTFormat::FormatTime(CMTStr &str,INT64 ctm,bool useSec/*=false*/)
  513. {
  514. tm ttm={};
  515. //---
  516. if(!SMTTime::ParseTime(ctm,&ttm))
  517. return(str.Str());
  518. //---
  519. if(useSec) str.Format(L"%02d:%02d:%02d",ttm.tm_hour,ttm.tm_min,ttm.tm_sec);
  520. else str.Format(L"%02d:%02d",ttm.tm_hour,ttm.tm_min);
  521. //---
  522. return(str.Str());
  523. }
  524. //+------------------------------------------------------------------+
  525. //| Format time |
  526. //+------------------------------------------------------------------+
  527. inline LPCWSTR SMTFormat::FormatTimeMsc(CMTStr &str,INT64 ctm,bool useSec/*=false*/)
  528. {
  529. tm ttm={};
  530. //---
  531. if(!SMTTime::ParseTime(ctm/1000,&ttm))
  532. return(str.Str());
  533. //---
  534. if(useSec) str.Format(L"%02d:%02d:%02d.%03d",ttm.tm_hour,ttm.tm_min,ttm.tm_sec,(int)(ctm%1000));
  535. else str.Format(L"%02d:%02d",ttm.tm_hour,ttm.tm_min);
  536. //---
  537. return(str.Str());
  538. }
  539. //+------------------------------------------------------------------+
  540. //| Format IP[:port] |
  541. //+------------------------------------------------------------------+
  542. inline LPCWSTR SMTFormat::FormatIP(CMTStr &str,const UINT ip,const UINT port/*=0*/)
  543. {
  544. if(port>0) str.Format(L"%d.%d.%d.%d:%u",ip&255,(ip>>8)&255,(ip>>16)&255,(ip>>24)&255,port);
  545. else str.Format(L"%d.%d.%d.%d", ip&255,(ip>>8)&255,(ip>>16)&255,(ip>>24)&255);
  546. //---
  547. return(str.Str());
  548. }
  549. //+------------------------------------------------------------------+
  550. //| Format IP[:port] |
  551. //+------------------------------------------------------------------+
  552. inline LPCWSTR SMTFormat::FormatIP(CMTStr &str,const USHORT *ip,const UINT port/*=0*/)
  553. {
  554. if(ip)
  555. {
  556. if(port>0)
  557. str.Format(L"[%04x:04x:04x:04x:04x:04x:04x:04x]:%u",
  558. ip[0],ip[1],ip[2],ip[3],ip[4],ip[5],ip[6],ip[7],port);
  559. else
  560. str.Format(L"[%04x:04x:04x:04x:04x:04x:04x:04x]",
  561. ip[0],ip[1],ip[2],ip[3],ip[4],ip[5],ip[6],ip[7]);
  562. }
  563. //---
  564. return(str.Str());
  565. }
  566. //+------------------------------------------------------------------+
  567. //| Position type |
  568. //+------------------------------------------------------------------+
  569. inline LPCWSTR SMTFormat::FormatPositionType(CMTStr &str,const UINT type)
  570. {
  571. //--- clear
  572. str.Clear();
  573. //--- check type
  574. switch(type)
  575. {
  576. case IMTPosition::POSITION_BUY : str.Assign(L"buy"); break;
  577. case IMTPosition::POSITION_SELL : str.Assign(L"sell"); break;
  578. }
  579. //--- return
  580. return(str.Str());
  581. }
  582. //+------------------------------------------------------------------+
  583. //| Order type |
  584. //+------------------------------------------------------------------+
  585. inline LPCWSTR SMTFormat::FormatOrderType(CMTStr &str,const UINT type)
  586. {
  587. //--- clear
  588. str.Clear();
  589. //--- check type
  590. switch(type)
  591. {
  592. case IMTOrder::OP_BUY : str.Assign(L"buy"); break;
  593. case IMTOrder::OP_SELL : str.Assign(L"sell"); break;
  594. case IMTOrder::OP_BUY_LIMIT : str.Assign(L"buy limit"); break;
  595. case IMTOrder::OP_SELL_LIMIT : str.Assign(L"sell limit"); break;
  596. case IMTOrder::OP_BUY_STOP : str.Assign(L"buy stop"); break;
  597. case IMTOrder::OP_SELL_STOP : str.Assign(L"sell stop"); break;
  598. case IMTOrder::OP_BUY_STOP_LIMIT : str.Assign(L"buy stop limit"); break;
  599. case IMTOrder::OP_SELL_STOP_LIMIT: str.Assign(L"sell stop limit"); break;
  600. }
  601. //--- return
  602. return(str.Str());
  603. }
  604. //+------------------------------------------------------------------+
  605. //| Order status |
  606. //+------------------------------------------------------------------+
  607. inline LPCWSTR SMTFormat::FormatOrderStatus(CMTStr &str,const UINT status)
  608. {
  609. //--- clear
  610. str.Clear();
  611. //--- check type
  612. switch(status)
  613. {
  614. case IMTOrder::ORDER_STATE_STARTED : str.Assign(L"started"); break;
  615. case IMTOrder::ORDER_STATE_PLACED : str.Assign(L"placed"); break;
  616. case IMTOrder::ORDER_STATE_CANCELED: str.Assign(L"canceled"); break;
  617. case IMTOrder::ORDER_STATE_PARTIAL : str.Assign(L"partial"); break;
  618. case IMTOrder::ORDER_STATE_FILLED : str.Assign(L"filled"); break;
  619. case IMTOrder::ORDER_STATE_REJECTED: str.Assign(L"rejected"); break;
  620. case IMTOrder::ORDER_STATE_EXPIRED : str.Assign(L"expired"); break;
  621. case IMTOrder::ORDER_STATE_REQUEST_ADD : str.Assign(L"request adding"); break;
  622. case IMTOrder::ORDER_STATE_REQUEST_MODIFY: str.Assign(L"request modification"); break;
  623. case IMTOrder::ORDER_STATE_REQUEST_CANCEL: str.Assign(L"request cancelling"); break;
  624. }
  625. //--- return
  626. return(str.Str());
  627. }
  628. //+------------------------------------------------------------------+
  629. //| Order filling type |
  630. //+------------------------------------------------------------------+
  631. inline LPCWSTR SMTFormat::FormatOrderTypeFilling(CMTStr &str,const UINT type)
  632. {
  633. //--- clear
  634. str.Clear();
  635. //--- check type
  636. switch(type)
  637. {
  638. case IMTOrder::ORDER_FILL_FOK : str.Assign(L"fill or kill"); break;
  639. case IMTOrder::ORDER_FILL_IOC : str.Assign(L"immediate or cancel"); break;
  640. case IMTOrder::ORDER_FILL_RETURN: str.Assign(L"return"); break;
  641. }
  642. //--- return
  643. return(str.Str());
  644. }
  645. //+------------------------------------------------------------------+
  646. //| Order expiration type |
  647. //+------------------------------------------------------------------+
  648. inline LPCWSTR SMTFormat::FormatOrderTypeTime(CMTStr &str,const UINT type)
  649. {
  650. //--- clear
  651. str.Clear();
  652. //--- check type
  653. switch(type)
  654. {
  655. case IMTOrder::ORDER_TIME_GTC : str.Assign(L"gtc"); break;
  656. case IMTOrder::ORDER_TIME_DAY : str.Assign(L"day"); break;
  657. case IMTOrder::ORDER_TIME_SPECIFIED: str.Assign(L"specified"); break;
  658. }
  659. //--- return
  660. return(str.Str());
  661. }
  662. //+------------------------------------------------------------------+
  663. //| Order reason |
  664. //+------------------------------------------------------------------+
  665. inline LPCWSTR SMTFormat::FormatOrderTypeReason(CMTStr &str,UINT reason)
  666. {
  667. //--- clear
  668. str.Clear();
  669. //--- check type
  670. switch(reason)
  671. {
  672. case IMTOrder::ORDER_REASON_CLIENT : str.Assign(L"Client"); break;
  673. case IMTOrder::ORDER_REASON_EXPERT : str.Assign(L"Expert"); break;
  674. case IMTOrder::ORDER_REASON_DEALER : str.Assign(L"Dealer"); break;
  675. case IMTOrder::ORDER_REASON_SL : str.Assign(L"Stop loss"); break;
  676. case IMTOrder::ORDER_REASON_TP : str.Assign(L"Take profit"); break;
  677. case IMTOrder::ORDER_REASON_SO : str.Assign(L"Stop out"); break;
  678. case IMTOrder::ORDER_REASON_ROLLOVER : str.Assign(L"Rollover"); break;
  679. case IMTOrder::ORDER_REASON_EXTERNAL_CLIENT : str.Assign(L"External Client"); break;
  680. case IMTOrder::ORDER_REASON_VMARGIN : str.Assign(L"Variation margin"); break;
  681. case IMTOrder::ORDER_REASON_GATEWAY : str.Assign(L"Gateway"); break;
  682. case IMTOrder::ORDER_REASON_SIGNAL : str.Assign(L"Signal"); break;
  683. case IMTOrder::ORDER_REASON_SETTLEMENT : str.Assign(L"Settlement"); break;
  684. case IMTOrder::ORDER_REASON_TRANSFER : str.Assign(L"Transfer"); break;
  685. case IMTOrder::ORDER_REASON_SYNC : str.Assign(L"Synchronization"); break;
  686. case IMTOrder::ORDER_REASON_EXTERNAL_SERVICE : str.Assign(L"External Service"); break;
  687. case IMTOrder::ORDER_REASON_MIGRATION : str.Assign(L"Migration"); break;
  688. case IMTOrder::ORDER_REASON_MOBILE : str.Assign(L"Mobile"); break;
  689. case IMTOrder::ORDER_REASON_WEB : str.Assign(L"Web"); break;
  690. case IMTOrder::ORDER_REASON_SPLIT : str.Assign(L"Split"); break;
  691. }
  692. //--- return
  693. return(str.Str());
  694. }
  695. //+------------------------------------------------------------------+
  696. //| Order price |
  697. //+------------------------------------------------------------------+
  698. inline LPCWSTR SMTFormat::FormatOrderPrice(CMTStr &str,const double price_order,const double price_trigger,const UINT digits)
  699. {
  700. CMTStr64 price,trigger;
  701. //--- clear
  702. str.Clear();
  703. //--- check trigger price
  704. if(price_trigger)
  705. {
  706. FormatPrice(price,price_order,digits);
  707. FormatPrice(trigger,price_trigger,digits);
  708. str.Format(L"%s (%s)",price.Str(),trigger.Str());
  709. }
  710. else
  711. {
  712. if(price_order!=0) FormatPrice(str,price_order,digits);
  713. else str.Assign(L"market");
  714. }
  715. //--- return
  716. return(str.Str());
  717. }
  718. //+------------------------------------------------------------------+
  719. //| Deal action |
  720. //+------------------------------------------------------------------+
  721. inline LPCWSTR SMTFormat::FormatDealAction(CMTStr &str,const UINT action)
  722. {
  723. //--- clear
  724. str.Clear();
  725. //--- check type
  726. switch(action)
  727. {
  728. case IMTDeal::DEAL_BUY : str.Assign(L"buy"); break;
  729. case IMTDeal::DEAL_SELL : str.Assign(L"sell"); break;
  730. case IMTDeal::DEAL_BALANCE : str.Assign(L"balance"); break;
  731. case IMTDeal::DEAL_CREDIT : str.Assign(L"credit"); break;
  732. case IMTDeal::DEAL_CHARGE : str.Assign(L"charge"); break;
  733. case IMTDeal::DEAL_CORRECTION: str.Assign(L"correction"); break;
  734. case IMTDeal::DEAL_BONUS : str.Assign(L"bonus"); break;
  735. case IMTDeal::DEAL_COMMISSION: str.Assign(L"commission"); break;
  736. case IMTDeal::DEAL_COMMISSION_DAILY : str.Assign(L"daily commission"); break;
  737. case IMTDeal::DEAL_COMMISSION_MONTHLY: str.Assign(L"monthly commission"); break;
  738. case IMTDeal::DEAL_AGENT_DAILY : str.Assign(L"daily agent commission"); break;
  739. case IMTDeal::DEAL_AGENT_MONTHLY : str.Assign(L"monthly agent commission"); break;
  740. case IMTDeal::DEAL_INTERESTRATE : str.Assign(L"interest rate"); break;
  741. case IMTDeal::DEAL_BUY_CANCELED : str.Assign(L"canceled buy"); break;
  742. case IMTDeal::DEAL_SELL_CANCELED : str.Assign(L"canceled sell"); break;
  743. case IMTDeal::DEAL_DIVIDEND : str.Assign(L"dividend"); break;
  744. case IMTDeal::DEAL_DIVIDEND_FRANKED : str.Assign(L"franked dividend"); break;
  745. case IMTDeal::DEAL_TAX : str.Assign(L"tax"); break;
  746. case IMTDeal::DEAL_AGENT : str.Assign(L"agent commission"); break;
  747. case IMTDeal::DEAL_SO_COMPENSATION : str.Assign(L"so compensation"); break;
  748. }
  749. //--- return
  750. return(str.Str());
  751. }
  752. //+------------------------------------------------------------------+
  753. //| Deal direction |
  754. //+------------------------------------------------------------------+
  755. inline LPCWSTR SMTFormat::FormatDealEntry(CMTStr &str,const UINT entry)
  756. {
  757. //--- clear
  758. str.Clear();
  759. //--- check type
  760. switch(entry)
  761. {
  762. case IMTDeal::ENTRY_IN : str.Assign(L"in"); break;
  763. case IMTDeal::ENTRY_OUT : str.Assign(L"out"); break;
  764. case IMTDeal::ENTRY_INOUT : str.Assign(L"in/out"); break;
  765. case IMTDeal::ENTRY_OUT_BY: str.Assign(L"out by"); break;
  766. }
  767. //--- return
  768. return(str.Str());
  769. }
  770. //+------------------------------------------------------------------+
  771. //| Modify flags |
  772. //+------------------------------------------------------------------+
  773. inline LPCWSTR SMTFormat::FormatModifyFlags(CMTStr &str,const UINT modify_flags)
  774. {
  775. //--- description
  776. static struct
  777. {
  778. UINT flag;
  779. LPCWSTR desc;
  780. } modify_flags_desc[]=
  781. {
  782. { IMTOrder::MODIFY_FLAGS_ADMIN, L"Administrator" },
  783. { IMTOrder::MODIFY_FLAGS_MANAGER, L"Manager" },
  784. { IMTOrder::MODIFY_FLAGS_POSITION, L"Position" },
  785. { IMTOrder::MODIFY_FLAGS_RESTORE, L"Restore" },
  786. { IMTOrder::MODIFY_FLAGS_API_ADMIN, L"Administrator API"},
  787. { IMTOrder::MODIFY_FLAGS_API_MANAGER, L"Manager API" },
  788. { IMTOrder::MODIFY_FLAGS_API_SERVER, L"Server API" },
  789. { IMTOrder::MODIFY_FLAGS_API_GATEWAY, L"Gateway API" }
  790. };
  791. //--- counter
  792. UINT added=0;
  793. //--- collect description
  794. str.Clear();
  795. for(UINT i=0;i<_countof(modify_flags_desc);i++)
  796. if(modify_flags_desc[i].flag&modify_flags)
  797. {
  798. //--- add comma
  799. if(added++)
  800. str.Append(L", ");
  801. //--- write
  802. str.Append(modify_flags_desc[i].desc);
  803. }
  804. //--- result
  805. return(str.Str());
  806. }
  807. //+------------------------------------------------------------------+
  808. //| |
  809. //+------------------------------------------------------------------+
  810. inline LPCWSTR SMTFormat::FormatDouble(CMTStr &str,UINT64 val,UINT digits)
  811. {
  812. static const wchar_t cd[]={ L'0',L'1',L'2',L'3',L'4',L'5',L'6',L'7',L'8',L'9',0 };
  813. wchar_t tmp[256]=L"",*cp,*dst;
  814. UINT i,len;
  815. //---
  816. str.Clear();
  817. cp=tmp;
  818. //--- check
  819. if(digits>8) return(str.Str());
  820. //---
  821. if(digits>0)
  822. {
  823. for(i=0;i<digits;i++)
  824. {
  825. *cp++=cd[val%10];
  826. val/=10;
  827. }
  828. *cp++=SIG_DECIMAL;
  829. }
  830. //--- integer part
  831. *cp++=cd[val%10];
  832. for(val/=10,i=1;val!=0;val/=10,i++)
  833. *cp++=cd[val%10];
  834. *cp=0;
  835. //--- check size
  836. len=UINT(cp-tmp);
  837. if(len>=str.Max()-1) return(str.Str());
  838. //--- string reverse
  839. dst=str.Buffer(); cp=tmp+len-1;
  840. while(cp>=tmp) *dst++=*cp--;
  841. *dst=0;
  842. str.Refresh();
  843. //---
  844. return(str.Str());
  845. }
  846. //+------------------------------------------------------------------+
  847. //| |
  848. //+------------------------------------------------------------------+
  849. inline LPCWSTR SMTFormat::FormatMoney(CMTStr &str,UINT64 val,UINT digits)
  850. {
  851. static const wchar_t cd[]={ L'0',L'1',L'2',L'3',L'4',L'5',L'6',L'7',L'8',L'9',0 };
  852. wchar_t tmp[256]=L"",*cp,*dst;
  853. UINT i,len;
  854. //---
  855. str.Clear();
  856. cp=tmp;
  857. //--- checks
  858. if(digits>8) return(str.Str());
  859. //---
  860. if(digits>0)
  861. {
  862. for(i=0;i<digits;i++)
  863. {
  864. *cp++=cd[val%10];
  865. val/=10;
  866. }
  867. *cp++=SIG_DECIMAL;
  868. }
  869. //--- integer part
  870. *cp++=cd[val%10];
  871. for(val/=10,i=1;val!=0;val/=10,i++)
  872. {
  873. if(i%3==0) *cp++=SIG_THOUSAND;
  874. *cp++=cd[val%10];
  875. }
  876. *cp=0;
  877. //--- check size
  878. len=UINT(cp-tmp);
  879. if(len>=str.Max()-1) return(str.Str());
  880. //--- reverse string
  881. dst=str.Buffer(); cp=tmp+len-1;
  882. while(cp>=tmp) *dst++=*cp--;
  883. *dst=0;
  884. str.Refresh();
  885. //---
  886. return(str.Str());
  887. }
  888. //+------------------------------------------------------------------+
  889. //| |
  890. //+------------------------------------------------------------------+
  891. inline void SMTFormat::TrimZeros(CMTStr &str,UINT extra_digits)
  892. {
  893. UINT len=str.Len(),digits=0;
  894. //--- remove zero
  895. while(len>0 && str[len-1]==L'0' && digits<extra_digits) { len--; digits++; }
  896. str.Trim(len);
  897. //--- remove points
  898. if(len>0 && str[len-1]==L'.') str.Trim(len-1);
  899. }
  900. //+------------------------------------------------------------------+