mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-11-30 15:06:50 -05:00
312 lines
No EOL
5.2 KiB
C++
312 lines
No EOL
5.2 KiB
C++
#include "tagz.h"
|
|
#include "functions.h"
|
|
#include <windows.h>
|
|
#include <shlwapi.h>
|
|
#include "api__tagz.h"
|
|
#include "resource.h"
|
|
|
|
void CopyChar(LPTSTR dest, LPCTSTR src)
|
|
{
|
|
LPTSTR end = CharNext(src);
|
|
int count = (int)(end-src);
|
|
if (count <= 0) return;
|
|
while (count--)
|
|
{
|
|
*dest++=*src++;
|
|
}
|
|
}
|
|
|
|
static int CharacterCompare(LPCTSTR ch1, LPCTSTR ch2)
|
|
{
|
|
TCHAR str1[3]={0,0,0}, str2[3]={0,0,0};
|
|
|
|
CopyChar(str1, ch1);
|
|
CopyChar(str2, ch2);
|
|
|
|
return memcmp(str1, str2, 3*sizeof(TCHAR));
|
|
}
|
|
|
|
static bool skipshit(wchar_t ** _p, wchar_t *skipCharacters)
|
|
{
|
|
LPTSTR p = *_p;
|
|
int paranCount = 0, bracketCount = 0;
|
|
while (p && *p)
|
|
{
|
|
if (!paranCount && !bracketCount && skipCharacters)
|
|
{
|
|
LPTSTR skipChar = skipCharacters;
|
|
while (skipChar && *skipChar)
|
|
{
|
|
if (!CharacterCompare(skipChar, p))
|
|
break;
|
|
skipChar++;
|
|
}
|
|
if (skipChar && *skipChar)
|
|
break;
|
|
}
|
|
|
|
if (*p == L'\'')
|
|
{
|
|
p = CharNext(p);
|
|
while (p && *p && *p != L'\'')
|
|
p = CharNext(p);
|
|
if (!p || p && !*p)
|
|
return 0;
|
|
}
|
|
else if (*p == L'(')
|
|
{
|
|
paranCount++;
|
|
}
|
|
else if (*p == L')')
|
|
{
|
|
if (--paranCount < 0)
|
|
return 0;
|
|
}
|
|
else if (*p == L'[')
|
|
{
|
|
bracketCount++;
|
|
}
|
|
else if (*p == L']')
|
|
{
|
|
if (--bracketCount < 0)
|
|
return 0;
|
|
}
|
|
p = CharNext(p);
|
|
}
|
|
*_p = p;
|
|
return *p && !paranCount && !bracketCount;
|
|
}
|
|
|
|
void FMT::run()
|
|
{
|
|
if (!spec)
|
|
{
|
|
Error();
|
|
return ;
|
|
}
|
|
while (spec && *spec)
|
|
{
|
|
if (*spec == L'%')
|
|
{
|
|
spec = CharNext(spec);
|
|
if (spec && *spec == L'%')
|
|
{
|
|
str.AddChar(L'%');
|
|
spec = CharNext(spec);
|
|
continue;
|
|
}
|
|
|
|
wchar_t *s1 = CharNext(spec);
|
|
while (s1 && *s1 && *s1 != L'%')
|
|
s1 = CharNext(s1);
|
|
|
|
if (!s1 || !*s1)
|
|
{
|
|
Error();
|
|
break;
|
|
}
|
|
|
|
*s1 = 0;
|
|
wchar_t *tag = tagProvider->GetTag(spec, parameters);
|
|
*s1 = L'%';
|
|
if (tag && tag[0])
|
|
{
|
|
found++;
|
|
str.AddString(tag);
|
|
}
|
|
else
|
|
{
|
|
// this isgay
|
|
//str.AddString(_TX("?"));
|
|
}
|
|
if (tag)
|
|
tagProvider->FreeTag(tag);
|
|
spec = CharNext(s1);
|
|
}
|
|
else if (*spec == L'$')
|
|
{
|
|
spec = CharNext(spec);
|
|
if (spec && *spec == L'$')
|
|
{
|
|
str.AddChar(L'$');
|
|
spec = CharNext(spec);
|
|
continue;
|
|
}
|
|
wchar_t *s1 = CharNext(spec);
|
|
while (s1 && *s1 && *s1 != L'(')
|
|
s1 = CharNext(s1);
|
|
|
|
if (!s1 || !*s1)
|
|
{
|
|
Error();
|
|
break;
|
|
}
|
|
wchar_t *s2 = CharNext(s1);
|
|
if (!skipshit(&s2, L")"))
|
|
{
|
|
Error();
|
|
break;
|
|
}
|
|
if (!s2 || !*s2)
|
|
{
|
|
Error();
|
|
break;
|
|
}
|
|
wchar_t *p = CharNext(s1);
|
|
wchar_t *temp[64] = {0};
|
|
size_t temp_f[64] = {0};
|
|
size_t nt = 0;
|
|
wchar_t *p1 = CharNext(s1);
|
|
while (p && p <= s2 && nt < 64)
|
|
{
|
|
if (!skipshit(&p, L",)"))
|
|
{
|
|
Error();
|
|
return ;
|
|
}
|
|
if (p > s2 || (*p != L',' && *p != L')'))
|
|
{
|
|
Error(WASABI_API_LNGSTRINGW(IDS_INTERNAL_ERROR));
|
|
return ;
|
|
}
|
|
wchar_t bk = *p;
|
|
*p = 0;
|
|
temp[nt] = _FMT(p1, &temp_f[nt]);
|
|
nt++;
|
|
*p = bk;;
|
|
p1 = CharNext(p);
|
|
p = CharNext(p);
|
|
}
|
|
*s1 = 0;
|
|
size_t n;
|
|
TEXTFUNC fn = 0;
|
|
for (n = 0;FUNCS[n].func;n++)
|
|
{
|
|
if (!StrCmpI(spec, FUNCS[n].name))
|
|
{
|
|
fn = FUNCS[n].func;
|
|
break;
|
|
}
|
|
}
|
|
*s1 = L'(';
|
|
if (fn)
|
|
{
|
|
fn(nt, temp, temp_f, &str, vars);
|
|
}
|
|
else
|
|
{
|
|
str.AddString(WASABI_API_LNGSTRINGW(IDS_UNKNOWN_FUNCTION));
|
|
}
|
|
for (n = 0;n < nt;n++)
|
|
free(temp[n]);
|
|
spec = CharNext(s2);
|
|
}
|
|
else if (*spec == L'\'')
|
|
{
|
|
spec = CharNext(spec);
|
|
if (spec && *spec == L'\'')
|
|
{
|
|
str.AddChar(L'\'');
|
|
spec++;
|
|
continue;
|
|
}
|
|
LPTSTR s1 = CharNext(spec);
|
|
while (s1 && *s1 && *s1 != L'\'')
|
|
s1 = CharNext(s1);
|
|
if (!s1 || !*s1)
|
|
{
|
|
Error();
|
|
break;
|
|
}
|
|
*s1 = 0;
|
|
str.AddString(spec);
|
|
*s1 = L'\'';
|
|
spec = CharNext(s1);
|
|
}
|
|
else if (*spec == L'[')
|
|
{
|
|
spec = CharNext(spec);
|
|
LPTSTR s1 = spec;
|
|
if (!skipshit(&s1, L"]"))
|
|
{
|
|
Error();
|
|
break;
|
|
}
|
|
wchar_t bk = *s1;
|
|
*s1 = 0;
|
|
FMT fmt(this, spec);
|
|
fmt.run();
|
|
if (fmt.found)
|
|
{
|
|
wchar_t *zz = fmt;
|
|
str.AddString(zz);
|
|
found += fmt.found;
|
|
free(zz);
|
|
}
|
|
*s1 = bk;
|
|
spec = CharNext(s1);
|
|
}
|
|
else if (*spec == L']' || *spec == L'(' || *spec == L')')
|
|
{
|
|
Error();
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
str.AddDBChar(spec);
|
|
spec = CharNext(spec);
|
|
}
|
|
}
|
|
}
|
|
|
|
FMT::FMT(const wchar_t *p_spec, ifc_tagprovider *_tagProvider, ifc_tagparams *_parameters, VarList * _vars)
|
|
: vars(_vars), tagProvider(_tagProvider), parameters(_parameters),
|
|
found(0)
|
|
{
|
|
org_spec = spec = _wcsdup(p_spec);
|
|
}
|
|
|
|
void FMT::Open(const wchar_t *p_spec, ifc_tagprovider *_tagProvider, ifc_tagparams *_parameters, VarList * _vars)
|
|
{
|
|
vars=_vars;
|
|
tagProvider = _tagProvider;
|
|
parameters = _parameters;
|
|
org_spec = spec = _wcsdup(p_spec);
|
|
}
|
|
|
|
FMT::operator LPTSTR()
|
|
{
|
|
run();
|
|
return str.GetBuf();
|
|
}
|
|
|
|
void FMT::Error(wchar_t *e)
|
|
{
|
|
str.Reset();
|
|
str.AddString(e ? e : WASABI_API_LNGSTRINGW(IDS_SYNTAX_ERROR_IN_STRING));
|
|
}
|
|
|
|
FMT::FMT(FMT* base, wchar_t *_spec)
|
|
{
|
|
vars = base->vars;
|
|
found = 0;
|
|
org_spec = 0;
|
|
tagProvider = base->tagProvider;
|
|
parameters=base->parameters;
|
|
spec = _spec;
|
|
}
|
|
|
|
wchar_t * FMT::_FMT(wchar_t * s, size_t *f)
|
|
{
|
|
FMT fmt(this, s);
|
|
wchar_t * c = (wchar_t *)fmt;
|
|
if (f) *f = fmt.found;
|
|
found += fmt.found;
|
|
return c;
|
|
}
|
|
|
|
FMT::~FMT()
|
|
{
|
|
if (org_spec)
|
|
free(org_spec);
|
|
} |