functions.cpp 19 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213
  1. #include "functions.h"
  2. #include "string.h"
  3. #include "varlist.h"
  4. #include <windows.h>
  5. #include <stddef.h>
  6. #include <shlwapi.h>
  7. #include "api__tagz.h"
  8. #include "resource.h"
  9. #include <strsafe.h>
  10. #define MAKEFUNC(X) static void X(size_t n_src, wchar_t **src,size_t *found_src, tagz_::string *out, VarList *vars)
  11. static bool StringMatch(const wchar_t *string1, const wchar_t *string2)
  12. {
  13. int comp = CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | /*NORM_IGNOREKANATYPE |*/ NORM_IGNOREWIDTH, string1, -1, string2, -1);
  14. return comp == CSTR_EQUAL;
  15. }
  16. /* ------ Logic ------ */
  17. #if 0
  18. MAKEFUNC(And)
  19. {
  20. if (n_src != 2)
  21. out->AddString("[INVALID $and SYNTAX]");
  22. else
  23. if (found_src[0] && found_src[1])
  24. out->AddString("true");
  25. }
  26. MAKEFUNC(Greater)
  27. {
  28. if (n_src != 2)
  29. out->AddString("[INVALID $greater SYNTAX]");
  30. else
  31. {
  32. if (_wtoi(src[0])>_wtoi(src[1]))
  33. out->AddString("true");
  34. }
  35. }
  36. #endif
  37. #if 0
  38. MAKEFUNC(_StrCmp)
  39. {
  40. if (n_src != 2)
  41. out->AddString("[INVALID $STRCMP SYNTAX]");
  42. else
  43. {
  44. int comp = CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | /*NORM_IGNOREKANATYPE |*/ NORM_IGNOREWIDTH, string1, -1, string2, -1);
  45. return comp == CSTR_EQUAL;
  46. }
  47. }
  48. #endif
  49. MAKEFUNC(IfStrEqual)
  50. {
  51. if (n_src != 3)
  52. out->AddString(WASABI_API_LNGSTRINGW(IDS_INVALID_IF_SYNTAX));
  53. else
  54. {
  55. if (StringMatch(src[0], src[1]))
  56. out->AddString(src[2]);
  57. }
  58. }
  59. MAKEFUNC(IfStrNotEqual)
  60. {
  61. if (n_src != 3)
  62. out->AddString(WASABI_API_LNGSTRINGW(IDS_INVALID_IF_SYNTAX));
  63. else
  64. {
  65. if (!StringMatch(src[0], src[1]))
  66. out->AddString(src[2]);
  67. }
  68. }
  69. MAKEFUNC(IfStrEqual2)
  70. {
  71. if (n_src != 4)
  72. out->AddString(WASABI_API_LNGSTRINGW(IDS_INVALID_IF_SYNTAX));
  73. else
  74. {
  75. if (StringMatch(src[0], src[1]))
  76. out->AddString(src[2]);
  77. else
  78. out->AddString(src[3]);
  79. }
  80. }
  81. MAKEFUNC(If)
  82. {
  83. if (n_src != 3)
  84. out->AddString(WASABI_API_LNGSTRINGW(IDS_INVALID_IF_SYNTAX));
  85. else
  86. out->AddString(src[found_src[0] ? 1 : 2]);
  87. }
  88. MAKEFUNC(If2)
  89. {
  90. if (n_src != 2)
  91. out->AddString(WASABI_API_LNGSTRINGW(IDS_INVALID_IF_SYNTAX));
  92. else
  93. out->AddString(src[found_src[0] ? 0 : 1]);
  94. }
  95. MAKEFUNC(If3)
  96. {
  97. if (!n_src)
  98. return;
  99. for (size_t i = 0; i != (n_src-1); i++)
  100. {
  101. if (found_src[i])
  102. {
  103. out->AddString(src[i]);
  104. return;
  105. }
  106. }
  107. out->AddString(src[n_src-1]);
  108. }
  109. MAKEFUNC(Decode)
  110. {
  111. if (n_src == 0)
  112. return;
  113. for (size_t s=1;s!=n_src;s+=2)
  114. {
  115. if ((s + 1) == n_src) // last (default) parameter
  116. {
  117. out->AddString(src[s]);
  118. return;
  119. }
  120. if (StringMatch(src[0], src[s]))
  121. {
  122. out->AddString(src[s+1]); // last parameter check (see above) ensures that this is safe
  123. return;
  124. }
  125. }
  126. }
  127. MAKEFUNC(Select)
  128. {
  129. size_t select = (src[0] ? _wtoi(src[0]) : 0);
  130. if (select<n_src)
  131. {
  132. out->AddString(src[select]);
  133. }
  134. }
  135. /* ------ Length ------ */
  136. static int NumChars(const wchar_t *x)
  137. {
  138. int count = 0;
  139. while (x && *x)
  140. {
  141. x = CharNext(x);
  142. count++;
  143. }
  144. return count;
  145. }
  146. MAKEFUNC(Iflonger)
  147. {
  148. if (n_src != 4) out->AddString(WASABI_API_LNGSTRINGW(IDS_INVALID_IFLONGER_SYNTAX));
  149. else
  150. {
  151. if (NumChars(src[0]) > _wtoi(src[1]))
  152. out->AddString(src[2]);
  153. else
  154. out->AddString(src[3]);
  155. }
  156. }
  157. MAKEFUNC(PadLeft)
  158. {
  159. if (n_src >= 2)
  160. {
  161. LPTSTR fill = L" ";
  162. if (n_src >= 3 && src[2][0])
  163. fill = src[2];
  164. int num = (src[1] ? _wtoi(src[1]) : 0);
  165. wchar_t *p = src[0];
  166. int strChars = NumChars(p);
  167. if (strChars<num)
  168. {
  169. size_t fl = lstrlen(fill);
  170. while (strChars != num)
  171. {
  172. out->AddChar(fill[(--num) % fl]);
  173. }
  174. }
  175. while (p && *p)
  176. {
  177. out->AddDBChar(p);
  178. p = CharNext(p);
  179. }
  180. }
  181. }
  182. MAKEFUNC(Pad)
  183. {
  184. if (n_src >= 2)
  185. {
  186. LPTSTR fill = L" ";
  187. if (n_src >= 3 && src[2][0])
  188. fill = src[2];
  189. int num = (src[1] ? _wtoi(src[1]) : 0);
  190. LPTSTR p = src[0];
  191. while (p && *p)
  192. {
  193. out->AddDBChar(p);
  194. p = CharNext(p);
  195. num--;
  196. }
  197. size_t fl = lstrlen(fill);
  198. while (num > 0)
  199. {
  200. out->AddChar(fill[(--num) % fl]);
  201. }
  202. }
  203. }
  204. MAKEFUNC(Cut)
  205. {
  206. if (n_src >= 2)
  207. {
  208. size_t num = (src[1] ? _wtoi(src[1]) : 0);
  209. LPTSTR p = src[0];
  210. while (p && *p && num)
  211. {
  212. out->AddDBChar(p);
  213. p = CharNext(p);
  214. num--;
  215. }
  216. }
  217. }
  218. // todo: benski> there's no way this works (fixed by DrO Mar 2009)
  219. MAKEFUNC(Right)
  220. {
  221. if (n_src >= 2)
  222. {
  223. size_t num = (src[1] ? _wtoi(src[1]) : 0);
  224. int offset = NumChars(src[0]) - (int)num;
  225. LPTSTR p = src[0];
  226. while (p && *p && offset--)
  227. {
  228. p = CharNext(p);
  229. }
  230. while (p && *p && num)
  231. {
  232. out->AddDBChar(p);
  233. p = CharNext(p);
  234. num--;
  235. }
  236. }
  237. }
  238. MAKEFUNC(PadCut)
  239. {
  240. if (n_src >= 2)
  241. {
  242. LPTSTR fill = L" ";
  243. if (n_src >= 3 && src[2][0]) fill = src[3];
  244. size_t num = (src[1] ? _wtoi(src[1]) : 0);
  245. LPTSTR p = src[0];
  246. while (p && *p && num > 0)
  247. {
  248. out->AddDBChar(p);
  249. p = CharNext(p);
  250. num--;
  251. }
  252. size_t fl = lstrlen(fill);
  253. while (num > 0)
  254. {
  255. out->AddChar(fill[(--num) % fl]);
  256. }
  257. }
  258. }
  259. MAKEFUNC(Longest)
  260. {
  261. LPTSTR ptr = 0;
  262. size_t m = 0;
  263. for (size_t n = 0;n != n_src;n++)
  264. {
  265. size_t l = NumChars(src[n]);
  266. if (l > m)
  267. {
  268. m = l;
  269. ptr = src[n];
  270. }
  271. }
  272. if (ptr)
  273. out->AddString(ptr);
  274. }
  275. MAKEFUNC(Shortest)
  276. {
  277. LPTSTR ptr = 0;
  278. size_t m = (size_t)(-1);
  279. for (size_t n = 0;n != n_src;n++)
  280. {
  281. size_t l = NumChars(src[n]);
  282. if (l < m)
  283. {
  284. m = l;
  285. ptr = src[n];
  286. }
  287. }
  288. if (ptr)
  289. out->AddString(ptr);
  290. }
  291. MAKEFUNC(Len)
  292. {
  293. if (n_src >= 1)
  294. out->AddInt(NumChars(src[0]));
  295. }
  296. /* ------ Case ------ */
  297. static void DBUpper(LPTSTR x)
  298. {
  299. LPTSTR end = CharNext(x);
  300. DWORD count = (DWORD)(end - x);
  301. CharUpperBuff(x, count);
  302. }
  303. static bool IsSpace(LPTSTR x)
  304. {
  305. LPTSTR end = CharNext(x);
  306. int count = (int)(end - x);
  307. WORD charType = 0;
  308. GetStringTypeEx(LOCALE_USER_DEFAULT,
  309. CT_CTYPE1,
  310. x,
  311. count,
  312. &charType);
  313. return !!(charType & C1_SPACE);
  314. }
  315. static bool IsWordEnd(LPTSTR x)
  316. {
  317. /* TODO: decide if we want to do this
  318. if (x == '\'')
  319. return false; // keeps words like "isn't" from capitalizing incorrectly, although it does break single quoted strings
  320. */
  321. LPTSTR end = CharNext(x);
  322. int count = (int)(end - x);
  323. WORD charType = 0;
  324. GetStringTypeEx(LOCALE_USER_DEFAULT,
  325. CT_CTYPE1,
  326. x,
  327. count,
  328. &charType);
  329. return !!(charType & C1_SPACE) || !!(charType & C1_PUNCT);
  330. }
  331. static int separator(TCHAR x)
  332. {
  333. if (!x
  334. || x == L' '
  335. || x == L'\t') return 1;
  336. if (x == L'\'' || x == L'_') return 0;
  337. return 0;
  338. }
  339. MAKEFUNC(Upper)
  340. {
  341. if (n_src >= 1)
  342. {
  343. CharUpper(src[0]);
  344. out->AddString(src[0]);
  345. }
  346. }
  347. MAKEFUNC(Lower)
  348. {
  349. if (n_src >= 1)
  350. {
  351. CharLower(src[0]);
  352. out->AddString(src[0]);
  353. }
  354. }
  355. MAKEFUNC(Caps)
  356. {
  357. if (n_src < 1) return ;
  358. int firstLetter = 1;
  359. CharLower(src[0]);
  360. LPTSTR sp = src[0];
  361. while (sp && *sp)
  362. {
  363. bool isSep = IsWordEnd(sp);
  364. if (!isSep && firstLetter)
  365. DBUpper(sp);
  366. sp = CharNext(sp);
  367. firstLetter = isSep;
  368. }
  369. out->AddString(src[0]);
  370. }
  371. MAKEFUNC(Caps2)
  372. {
  373. if (n_src < 1) return ;
  374. int firstLetter = 1;
  375. LPTSTR sp = src[0];
  376. while (sp && *sp)
  377. {
  378. int isSep = IsWordEnd(sp);
  379. if (!isSep && firstLetter)
  380. DBUpper(sp);
  381. sp = CharNext(sp);
  382. firstLetter = isSep;
  383. }
  384. out->AddString(src[0]);
  385. }
  386. /* ------ Numbers ------ */
  387. MAKEFUNC(Num)
  388. {
  389. if (n_src == 2)
  390. {
  391. wchar_t tmp[16] = {0};
  392. StringCbPrintfW(tmp, sizeof(tmp), L"%0*u", (src[1] ? _wtoi(src[1]) : 0), (src[0] ? _wtoi(src[0]) : 0));
  393. out->AddString(tmp);
  394. }
  395. }
  396. MAKEFUNC(Hex)
  397. {
  398. if (n_src == 2)
  399. {
  400. wchar_t tmp[16] = {0};
  401. StringCbPrintfW(tmp, sizeof(tmp), L"%0*x", (src[1] ? _wtoi(src[1]) : 0), (src[0] ? _wtoi(src[0]) : 0));
  402. out->AddString(tmp);
  403. }
  404. }
  405. /* ------ Time ------ */
  406. MAKEFUNC(SysTime_year)
  407. {
  408. SYSTEMTIME st = {0};
  409. GetLocalTime(&st);
  410. wchar_t tmp[16] = {0};
  411. StringCbPrintfW(tmp, sizeof(tmp), L"%u",st.wYear);
  412. out->AddString(tmp);
  413. }
  414. MAKEFUNC(SysTime_month) //these are for stream saving, time in filenames
  415. {
  416. SYSTEMTIME st = {0};
  417. GetLocalTime(&st);
  418. wchar_t tmp[16] = {0};
  419. StringCbPrintfW(tmp, sizeof(tmp), L"%02u",st.wMonth);
  420. out->AddString(tmp);
  421. }
  422. MAKEFUNC(SysTime_day)
  423. {
  424. SYSTEMTIME st = {0};
  425. GetLocalTime(&st);
  426. wchar_t tmp[16] = {0};
  427. StringCbPrintfW(tmp, sizeof(tmp), L"%02u",st.wDay);
  428. out->AddString(tmp);
  429. }
  430. MAKEFUNC(SysTime_hour)
  431. {
  432. SYSTEMTIME st = {0};
  433. GetLocalTime(&st);
  434. wchar_t tmp[16] = {0};
  435. StringCbPrintfW(tmp, sizeof(tmp), L"%02u",st.wHour);
  436. out->AddString(tmp);
  437. }
  438. MAKEFUNC(SysTime_minute)
  439. {
  440. SYSTEMTIME st = {0};
  441. GetLocalTime(&st);
  442. wchar_t tmp[16] = {0};
  443. StringCbPrintfW(tmp, sizeof(tmp), L"%02u",st.wMinute);
  444. out->AddString(tmp);
  445. }
  446. MAKEFUNC(SysTime_second)
  447. {
  448. SYSTEMTIME st = {0};
  449. GetLocalTime(&st);
  450. wchar_t tmp[16] = {0};
  451. StringCbPrintfW(tmp, sizeof(tmp), L"%02u",st.wSecond);
  452. out->AddString(tmp);
  453. }
  454. /* ------ Math ------ */
  455. MAKEFUNC(Ifgreater)
  456. {
  457. if (n_src!=4)
  458. out->AddString(WASABI_API_LNGSTRINGW(IDS_INVALID_IFGREATER_SYNTAX));
  459. else
  460. {
  461. if ((src[0] ? _wtoi(src[0]) : 0) > (src[1] ? _wtoi(src[1]) : 0))
  462. out->AddString(src[2]);
  463. else
  464. out->AddString(src[3]);
  465. }
  466. }
  467. MAKEFUNC(Add)
  468. {
  469. int s=0;
  470. for (size_t n=0;n!=n_src;n++)
  471. {
  472. s += (src[n] ? _wtoi(src[n]) : 0);
  473. }
  474. out->AddInt(s);
  475. }
  476. MAKEFUNC(Sub)
  477. {
  478. if (n_src>=1)
  479. {
  480. int s = (src[0] ? _wtoi(src[0]) : 0);
  481. for (size_t n=1;n!=n_src;n++)
  482. {
  483. s -= (src[n] ? _wtoi(src[n]) : 0);
  484. }
  485. out->AddInt(s);
  486. }
  487. }
  488. MAKEFUNC(Mul)
  489. {
  490. int s=1;
  491. for (size_t n=0;n!=n_src;n++)
  492. {
  493. s *= (src[n] ? _wtoi(src[n]) : 1);
  494. }
  495. out->AddInt(s);
  496. }
  497. MAKEFUNC(Div)
  498. {
  499. if (n_src>=1)
  500. {
  501. int s = (src[0] ? _wtoi(src[0]) : 0);
  502. for (size_t n = 1; n != n_src; n++)
  503. {
  504. int t = (src[n] ? _wtoi(src[n]) : 0);
  505. if (t) s /= t;
  506. else t = 0;
  507. }
  508. out->AddInt(s);
  509. }
  510. }
  511. MAKEFUNC(Mod)
  512. {
  513. if (n_src>=1)
  514. {
  515. int s = (src[0] ? _wtoi(src[0]) : 0);
  516. for (size_t n = 1; n != n_src; n++)
  517. {
  518. int t = (src[n] ? _wtoi(src[n]) : 0);
  519. if (t) s %= t;
  520. else t = 0;
  521. }
  522. out->AddInt(s);
  523. }
  524. }
  525. MAKEFUNC(_MulDiv)
  526. {
  527. if (n_src == 3)
  528. {
  529. out->AddInt(MulDiv(_wtoi(src[0]), _wtoi(src[1]), _wtoi(src[2])));
  530. }
  531. }
  532. MAKEFUNC(Max)
  533. {
  534. if (!n_src) return;
  535. int m = (src[0] ? _wtoi(src[0]) : 0);
  536. for (size_t n = 1; n < n_src; n++)
  537. {
  538. int t = (src[n] ? _wtoi(src[n]) : 0);
  539. if (t > m) m = t;
  540. }
  541. out->AddInt(m);
  542. }
  543. MAKEFUNC(Min)
  544. {
  545. if (!n_src) return;
  546. int m = (src[0] ? _wtoi(src[0]) : 0);
  547. for (size_t n = 1; n < n_src; n++)
  548. {
  549. int t = (src[n] ? _wtoi(src[n]) : 0);
  550. if (t < m) m = t;
  551. }
  552. out->AddInt(m);
  553. }
  554. /* ------ Path ------ */
  555. MAKEFUNC(PathSafe)
  556. {
  557. LPTSTR p=src[0];
  558. while (p && *p)
  559. {
  560. if (*p <= 31 && *p >= 0)
  561. {
  562. // we'll just skip these characters
  563. }
  564. else switch (*p)
  565. {
  566. case L'?':
  567. case L'*':
  568. case L'|':
  569. out->AddDBChar(L"_");
  570. break;
  571. case '/':
  572. case L'\\':
  573. case L':':
  574. out->AddDBChar(L"-");
  575. break;
  576. case L'\"':
  577. out->AddDBChar(L"\'");
  578. break;
  579. case L'<':
  580. out->AddDBChar(L"(");
  581. break;
  582. case L'>':
  583. out->AddDBChar(L")");
  584. break;
  585. default:
  586. out->AddDBChar(p);
  587. }
  588. p = CharNext(p);
  589. }
  590. }
  591. MAKEFUNC(FileName)
  592. {
  593. if (n_src < 1) return ;
  594. out->AddString(PathFindFileName(src[0]));
  595. }
  596. MAKEFUNC(FilePart)
  597. {
  598. if (n_src < 1) return;
  599. LPTSTR beg = PathFindFileName(src[0]);
  600. LPTSTR end = PathFindExtension(beg);
  601. while (beg != end)
  602. {
  603. out->AddChar(*beg++);
  604. }
  605. }
  606. MAKEFUNC(PathRTrim)
  607. {
  608. if (n_src < 1) return;
  609. int cut=1;
  610. if (n_src>=2)
  611. cut = (src[1] ? _wtoi(src[1]) : 0);
  612. if (cut<0)
  613. cut=0;
  614. wchar_t folder[MAX_PATH] = {0};
  615. lstrcpyn(folder, src[0], MAX_PATH);
  616. while (cut--)
  617. {
  618. PathRemoveFileSpec(folder);
  619. PathRemoveBackslash(folder);
  620. }
  621. out->AddString(folder);
  622. }
  623. MAKEFUNC(PathLPart)
  624. {
  625. if (n_src < 1) return;
  626. int cut=1;
  627. if (n_src>=2)
  628. cut = (src[1] ? _wtoi(src[1]) : 0);
  629. if (cut<0)
  630. cut=0;
  631. wchar_t *p = src[0];
  632. while (cut-- && p)
  633. {
  634. p = PathFindNextComponent(p);
  635. }
  636. if (p)
  637. *p = 0;
  638. PathRemoveBackslash(src[0]);
  639. out->AddString(src[0]);
  640. }
  641. MAKEFUNC(PathRPart)
  642. {
  643. if (n_src < 1) return;
  644. int cut=1;
  645. if (n_src>=2)
  646. cut = (src[1] ? _wtoi(src[1]) : 0);
  647. if (cut<0)
  648. cut=0;
  649. wchar_t temp[MAX_PATH] = {0};
  650. lstrcpyn(temp, src[0], MAX_PATH);
  651. while (cut--)
  652. {
  653. PathRemoveBackslash(temp);
  654. PathRemoveFileSpec(temp);
  655. PathAddBackslash(temp);
  656. }
  657. out->AddString(&(src[0][lstrlenW(temp)]));
  658. }
  659. MAKEFUNC(PathLTrim)
  660. {
  661. if (n_src < 1) return;
  662. int cut=1;
  663. if (n_src>=2)
  664. cut = (src[1] ? _wtoi(src[1]) : 0);
  665. if (cut<0)
  666. cut=0;
  667. wchar_t *p = src[0];
  668. while (cut-- && p)
  669. {
  670. p = PathFindNextComponent(p);
  671. }
  672. if (p)
  673. out->AddString(p);
  674. }
  675. MAKEFUNC(FileExt)
  676. {
  677. if (n_src < 1) return ;
  678. LPTSTR ext = PathFindExtension(src[0]);
  679. if (ext) ext = CharNext(ext);
  680. out->AddString(ext);
  681. }
  682. /* ------ Strings ------ */
  683. static wchar_t roman_num[]=
  684. {
  685. L'I',L'V',L'X',L'L',L'C',L'D',L'M'
  686. };
  687. static bool IsRoman(LPTSTR ptr)//could be more smart i think
  688. {
  689. if (ptr[0]==']' && ptr[1]=='[' && IsSpace(ptr+2))
  690. return true;
  691. while (!IsSpace(ptr))
  692. {
  693. bool found = 0;
  694. for (size_t n = 0; n < TABSIZE(roman_num); n++)
  695. {
  696. if (*ptr==roman_num[n])
  697. {
  698. found=1;
  699. break;
  700. }
  701. }
  702. if (!found)
  703. return false;
  704. ptr=CharNext(ptr);
  705. }
  706. return true;
  707. }
  708. static bool IsDigit(LPTSTR x)
  709. {
  710. LPTSTR end = CharNext(x);
  711. int count = (int)(end - x);
  712. WORD charType = 0;
  713. GetStringTypeEx(LOCALE_USER_DEFAULT,
  714. CT_CTYPE1,
  715. x,
  716. count,
  717. &charType);
  718. return !!(charType & C1_DIGIT);
  719. }
  720. // TODO: what's this do exactly???
  721. static bool sepcmp(LPTSTR src, LPTSTR val)
  722. {
  723. int l=lstrlen(val);
  724. return !StrCmpNI(src,val,l) && IsSpace(&src[l]);
  725. }
  726. static bool need_full(LPTSTR ptr)
  727. {
  728. if (IsRoman(ptr))
  729. return true;
  730. if (sepcmp(ptr, L"RPG"))
  731. return true;
  732. while (ptr && !IsSpace(ptr))
  733. {
  734. if (!ptr || !*ptr || !IsDigit(ptr))
  735. return false;
  736. ptr = CharNext(ptr);
  737. }
  738. return true;
  739. }
  740. static bool CharMatch(LPTSTR string1, LPTSTR string2)
  741. {
  742. LPTSTR end1 = CharNext(string1);
  743. LPTSTR end2 = CharNext(string2);
  744. int count1 = (int)(end1 - string1);
  745. int count2 = (int)(end2 - string2);
  746. if (count1 == count2)
  747. {
  748. int comp = CompareString(LOCALE_USER_DEFAULT, /*NORM_IGNORECASE |*/ /*NORM_IGNOREKANATYPE |*/ NORM_IGNOREWIDTH, string1, count1, string2, count2);
  749. return comp == CSTR_EQUAL;
  750. }
  751. else
  752. return false;
  753. }
  754. MAKEFUNC(_StrChr)
  755. {
  756. if (n_src == 2)
  757. {
  758. LPTSTR p = src[0];
  759. LPTSTR s = src[1];
  760. while (p && *p)
  761. {
  762. if (CharMatch(p, s))
  763. {
  764. out->AddInt(1 + (int)(p - src[0]));
  765. return ;
  766. }
  767. p = CharNext(p);
  768. }
  769. out->AddChar('0');
  770. }
  771. }
  772. MAKEFUNC(_StrRChr)
  773. {
  774. if (n_src == 2)
  775. {
  776. LPTSTR p = src[0], p1 = p;
  777. LPTSTR s = src[1];
  778. while (p && *p)
  779. {
  780. p1 = p;
  781. p = CharNext(p);
  782. }
  783. while (1)
  784. {
  785. if (CharMatch(p1, s))
  786. {
  787. out->AddInt(1 + (int)(p1 - src[0]));
  788. return ;
  789. }
  790. if (src[0] == p1)
  791. break;
  792. p1 = CharPrev(src[0], p1);
  793. }
  794. out->AddChar(L'0');
  795. }
  796. }
  797. MAKEFUNC(_StrStr)
  798. {
  799. // TODO: not multi-byte or unicode correct, but we'll deal for now
  800. if (n_src == 2)
  801. {
  802. LPTSTR p = StrStr(src[0], src[1]);
  803. if (p)
  804. out->AddInt(1 + (int)(p - src[0]));
  805. else
  806. out->AddChar(L'0');
  807. }
  808. }
  809. MAKEFUNC(SubStr)
  810. {
  811. int n1, n2;
  812. if (n_src < 2)
  813. return ;
  814. n1 = (src[1] ? _wtoi(src[1]) : 0);
  815. if (n_src >= 3)
  816. {
  817. n2 = (src[2] ? _wtoi(src[2]) : 0);
  818. }
  819. else
  820. n2 = n1;
  821. if (n1 < 1)
  822. n1 = 1;
  823. if (n2 >= n1)
  824. {
  825. n1--;
  826. n2--;
  827. LPTSTR p=src[0];
  828. while (n1 <= n2 && p && *p)
  829. {
  830. out->AddDBChar(p);
  831. p = CharNext(p);
  832. }
  833. }
  834. }
  835. MAKEFUNC(Split)
  836. {
  837. if (n_src!=3 || !src[0])
  838. return;
  839. LPTSTR p=src[0];
  840. LPTSTR split=src[1];
  841. int which = (src[2] ? _wtoi(src[2]) : 0);
  842. if (which)
  843. {
  844. LPCTSTR where = wcsstr(p, split);
  845. if (where)
  846. {
  847. where += wcslen(split);
  848. out->AddString(where);
  849. }
  850. }
  851. else
  852. {
  853. LPCTSTR where = wcsstr(p, split);
  854. if (where)
  855. {
  856. while (p != where)
  857. out->AddChar(*p++);
  858. }
  859. else
  860. out->AddString(p);
  861. }
  862. }
  863. MAKEFUNC(Replace)
  864. {
  865. if (n_src<3 || !src[0])
  866. return;
  867. LPTSTR p=src[0];
  868. while (p && *p)
  869. {
  870. LPTSTR p2 = p;
  871. LPTSTR src1 = src[1];
  872. while (src1 && *src1 && CharMatch(src1, p2))
  873. {
  874. p2 = CharNext(p2);
  875. src1 = CharNext(src1);
  876. }
  877. if (!*src1)
  878. {
  879. out->AddString(src[2]);
  880. p = p2;
  881. }
  882. else
  883. {
  884. out->AddDBChar(p);
  885. p = CharNext(p);
  886. }
  887. }
  888. }
  889. MAKEFUNC(Trim)
  890. {
  891. LPTSTR stringStart = src[0];
  892. // trim from beginning
  893. while (IsSpace(stringStart))
  894. stringStart = CharNext(stringStart);
  895. // trim from end
  896. LPTSTR stringLast = stringStart+lstrlen(stringStart)+1;
  897. stringLast=CharPrev(stringStart, stringLast); // have to go back from the null terminator in case the last char is multibyte
  898. while (IsSpace(stringLast))
  899. {
  900. stringLast= CharPrev(stringStart, stringLast);
  901. }
  902. stringLast = CharNext(stringLast);
  903. while (stringStart != stringLast)
  904. {
  905. out->AddChar(*stringStart++);
  906. }
  907. }
  908. /* ------ Generators ------ */
  909. MAKEFUNC(Tab)
  910. {
  911. int num=1;
  912. if (n_src == 1)
  913. num = (src[0] ? _wtoi(src[0]) : 0);
  914. while (num--)
  915. out->AddChar(L'\t');
  916. }
  917. MAKEFUNC(Crlf)
  918. {
  919. out->AddString(L"\r\n");
  920. }
  921. MAKEFUNC(Char)
  922. {
  923. if (n_src != 1)
  924. return;
  925. wchar_t wide[2]={ (wchar_t)(src[0] ? _wtoi(src[0]) : 0),(wchar_t)0};
  926. out->AddString(wide);
  927. /* below doesn't seem to work. not sure why
  928. wchar_t wide[5]={0,}; // 5 words just in case we go outside the BMP
  929. int ucs4[2] = {0,0}; // incoming value is encoded in UCS-4 (little endian)
  930. ucs4[0] = _wtoi(src[0]);
  931. int x = MultiByteToWideChar(12000, 0, (char*)ucs4, 4, wide, 5); // convert from UCS-4 to UTF-16
  932. int error = GetLastError();
  933. */
  934. }
  935. MAKEFUNC(Repeat)
  936. {
  937. if (n_src!=2)
  938. return;
  939. LPTSTR fillChar=src[0];
  940. int fillCount=(src[1] ? _wtoi(src[1]) : 0);
  941. if (fillCount<0)
  942. return;
  943. while (fillCount--)
  944. {
  945. out->AddString(fillChar);
  946. }
  947. }
  948. /* ------ Misc ------ */
  949. MAKEFUNC(Abbr)
  950. {
  951. //abbr(string,len)
  952. if (n_src == 0 || n_src > 2)
  953. return;
  954. if (n_src==2 && NumChars(src[0]) < (src[1] ? _wtoi(src[1]) : 0))
  955. {
  956. out->AddString(src[0]);
  957. return;
  958. }
  959. LPTSTR meta=src[0];
  960. bool w=0,r=0;
  961. while (meta && *meta)
  962. {
  963. bool an=!IsSpace(meta) || *meta==']' || *meta=='[';
  964. if (w && !an)
  965. {
  966. w=0;
  967. }
  968. else if (!w && an)
  969. {
  970. w=1;
  971. r=need_full(meta)?1:0;
  972. out->AddDBChar(meta);
  973. }
  974. else if (w && r)
  975. {
  976. out->AddDBChar(meta);
  977. }
  978. meta=CharNext(meta);
  979. }
  980. }
  981. MAKEFUNC(Get)
  982. {
  983. if (n_src >= 1)
  984. {
  985. wchar_t *p = vars->Get(src[0]);
  986. if (p)
  987. out->AddString(p);
  988. }
  989. }
  990. MAKEFUNC(Put)
  991. {
  992. if (n_src >= 2)
  993. {
  994. vars->Put(src[0], src[1]);
  995. out->AddString(src[1]);
  996. }
  997. }
  998. MAKEFUNC(PutQ)
  999. {
  1000. if (n_src >= 2)
  1001. {
  1002. vars->Put(src[0], src[1]);
  1003. }
  1004. }
  1005. MAKEFUNC(Null)
  1006. {
  1007. }
  1008. MAKEFUNC(Directory)
  1009. {
  1010. int numLevels=1;
  1011. if (n_src == 2)
  1012. numLevels = (src[1] ? _wtoi(src[1]) : 0);
  1013. wchar_t folder[MAX_PATH] = {0};
  1014. lstrcpyn(folder, (src[0] ? src[0] : L""), MAX_PATH);
  1015. while (numLevels--)
  1016. {
  1017. PathRemoveFileSpec(folder);
  1018. PathRemoveBackslash(folder);
  1019. }
  1020. PathStripPath(folder);
  1021. out->AddString(folder);
  1022. }
  1023. // TODO: order these or sort these, and use a binary search
  1024. TextFunction FUNCS[]=
  1025. {
  1026. // Blah,"blah",
  1027. // Nop,"nop",
  1028. If,L"if",
  1029. If2,L"if2",
  1030. If3, L"if3",
  1031. Upper,L"upper",
  1032. Lower,L"lower",
  1033. Pad,L"pad",
  1034. Cut,L"cut",
  1035. Cut,L"left",
  1036. PadCut,L"padcut",
  1037. Abbr,L"abbr",
  1038. FilePart,L"filepart",
  1039. FilePart,L"filename",
  1040. FileExt,L"fileext",
  1041. FileExt,L"ext",
  1042. PathLTrim,L"PathLTrim",
  1043. PathLPart,L"PathLPart",
  1044. PathRTrim,L"PathRTrim",
  1045. PathRPart,L"PathRPart",
  1046. Caps,L"caps",
  1047. Caps2,L"caps2",
  1048. Longest,L"longest",
  1049. Shortest,L"shortest",
  1050. Iflonger,L"iflonger",
  1051. Ifgreater,L"ifgreater",
  1052. Num,L"num",Num,L"dec",
  1053. Hex,L"hex",
  1054. _StrChr,L"strchr",
  1055. _StrChr,L"strlchr",
  1056. _StrRChr,L"strrchr",
  1057. _StrStr,L"strstr",
  1058. SubStr,L"substr",
  1059. Len,L"len",
  1060. Add,L"add",
  1061. Sub,L"sub",
  1062. Mul,L"mul",
  1063. Div,L"div",
  1064. Mod,L"mod",
  1065. _MulDiv, L"muldiv",
  1066. FileName,L"filename",
  1067. Min,L"min",
  1068. Max,L"max",
  1069. Get,L"get",
  1070. Put,L"put",
  1071. PutQ,L"puts",
  1072. Null,L"null",
  1073. SysTime_year,L"systime_year",
  1074. SysTime_month,L"systime_month",
  1075. SysTime_day,L"systime_day",
  1076. SysTime_hour,L"systime_hour",
  1077. SysTime_minute,L"systime_minute",
  1078. SysTime_second,L"systime_second",
  1079. Replace,L"replace",
  1080. Repeat, L"repeat",
  1081. PadLeft, L"lpad",
  1082. IfStrEqual, L"IfStrEqual",
  1083. IfStrEqual2, L"IfStrEqual2",
  1084. IfStrNotEqual, L"IfStrNotEqual",
  1085. Decode, L"decode",
  1086. //And, L"and",
  1087. //Greater,L"greater",
  1088. Char, L"char",
  1089. Crlf, L"crlf",
  1090. Directory, L"directory",
  1091. Right, L"right",
  1092. Tab, L"tab",
  1093. Trim, L"trim",
  1094. Select, L"select",
  1095. PathSafe, L"pathsafe",
  1096. Split, L"split",
  1097. 0,0,
  1098. };