mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
484 lines
13 KiB
484 lines
13 KiB
////////////////////////////////////////
|
|
// token.cpp
|
|
////////////////////////////////////////
|
|
//
|
|
// This file handle all the token strings
|
|
//
|
|
////////////////////////////////////////
|
|
|
|
#include "token.h"
|
|
#include "main.h"
|
|
|
|
extern CMainApp theApp;
|
|
#define MAX_TOKEN 8192
|
|
|
|
CToken::CToken()
|
|
{
|
|
m_uiTypeID = 0;
|
|
m_uiResID = 0;
|
|
m_uiItemID = 0;
|
|
m_uiFlags = 0;
|
|
m_uiStatusFlags = 0;
|
|
m_uiLastError = 0;
|
|
m_strItemName = "";
|
|
m_strSrcText = "";
|
|
m_strTgtText = "";
|
|
|
|
}
|
|
|
|
int CToken::Parse(CString strSrc, CString strTgt)
|
|
{
|
|
CString strSrcTokenID;
|
|
int pos;
|
|
|
|
if(!strSrc.IsEmpty())
|
|
{
|
|
pos = strSrc.Find('=');
|
|
if(pos==-1)
|
|
{
|
|
theApp.WriteCon(CONERR, "Invalid token [equal sign missing]\t%s\r\n", strSrc);
|
|
theApp.SetReturn(ERROR_RET_INVALID_TOKEN);
|
|
return CMainApp::ERR_TOKEN_WRONGFORMAT;
|
|
}
|
|
|
|
strSrcTokenID = strSrc.Left(pos-3);
|
|
m_strSrcText = strSrc.Right(strSrc.GetLength()-++pos);
|
|
pos = m_strSrcText.Find('\n');
|
|
if(pos!=-1)
|
|
m_strSrcText = m_strSrcText.Left(pos);
|
|
}
|
|
else
|
|
m_strSrcText = "";
|
|
|
|
pos = strTgt.Find('=');
|
|
if(pos==-1)
|
|
{
|
|
theApp.WriteCon(CONERR, "Invalid token [equal sign missing]\t%s\r\n", strTgt);
|
|
theApp.SetReturn(ERROR_RET_INVALID_TOKEN);
|
|
return CMainApp::ERR_TOKEN_WRONGFORMAT;
|
|
}
|
|
|
|
if(pos<=3)
|
|
{
|
|
theApp.WriteCon(CONERR, "Invalid token [token corruption]\t%s\r\n", strTgt);
|
|
theApp.SetReturn(ERROR_RET_INVALID_TOKEN);
|
|
return CMainApp::ERR_TOKEN_WRONGFORMAT;
|
|
}
|
|
|
|
m_strTokenID = strTgt.Left(pos-3);
|
|
m_strTgtText = strTgt.Right(strTgt.GetLength()-++pos);
|
|
|
|
//pos = m_strTgtText.Find('\n');
|
|
//if(pos!=-1)
|
|
// m_strTgtText = m_strTgtText.Left(pos);
|
|
//
|
|
// On FE platforms, "Find" could not find the
|
|
// ending \n when the last char is a High ansi because it is leadbyte.
|
|
|
|
char * pStr = m_strTgtText.GetBuffer(0);
|
|
pos = 0;
|
|
while (*pStr){
|
|
if(*pStr == '\n'){
|
|
m_strTgtText = m_strTgtText.Left(pos);
|
|
break;
|
|
}
|
|
if (IsDBCSLeadByteEx(theApp.GetUICodePage(), *pStr))
|
|
{
|
|
pos+=2;
|
|
}
|
|
else
|
|
{
|
|
pos++;
|
|
}
|
|
pStr = CharNextExA((WORD)theApp.GetUICodePage(), pStr, 0);
|
|
}
|
|
|
|
if(5>sscanf(m_strTokenID, TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]"),
|
|
&m_uiTypeID,
|
|
&m_uiResID,
|
|
&m_uiItemID,
|
|
&m_uiFlags,
|
|
&m_uiStatusFlags,
|
|
m_strItemName.GetBuffer(128)))
|
|
{
|
|
theApp.WriteCon(CONERR, "Invalid token [not enough arguments converted]\t%s\"]]\r\n", m_strTokenID);
|
|
theApp.SetReturn(ERROR_RET_INVALID_TOKEN);
|
|
return CMainApp::ERR_TOKEN_WRONGFORMAT;
|
|
}
|
|
|
|
// Special case the Menu Popup
|
|
if(m_uiTypeID==4 && (m_uiFlags & ISPOPUP)==ISPOPUP && (m_uiFlags & OLD_POPUP_ID)==OLD_POPUP_ID)
|
|
{
|
|
m_uiItemID = MAKELONG( 0xFFFF, LOWORD(m_uiItemID) );
|
|
}
|
|
|
|
m_strItemName.ReleaseBuffer();
|
|
m_strItemName = m_strTokenID.Mid(m_strTokenID.Find("|\"")+2);
|
|
|
|
if(!strSrc.IsEmpty())
|
|
{
|
|
// Perform a consistency check on the token files
|
|
unsigned int uiTypeID = 0;
|
|
unsigned int uiResID = 0;
|
|
unsigned int uiItemID = 0;
|
|
unsigned int uiFlags = 0;
|
|
unsigned int uiStatusFlags = 0;
|
|
CString strItemName = "";
|
|
|
|
sscanf(strSrcTokenID, TEXT("[[%u|%u|%u|%u|%u|\"%s\"]]"),
|
|
&uiTypeID,
|
|
&uiResID,
|
|
&uiItemID,
|
|
&uiFlags,
|
|
&uiStatusFlags,
|
|
strItemName.GetBuffer(128));
|
|
|
|
strItemName.ReleaseBuffer();
|
|
strItemName = strSrcTokenID.Mid(strSrcTokenID.Find("|\"")+2);
|
|
|
|
// Special case the Menu Popup
|
|
if(uiTypeID==4 && (uiFlags & ISPOPUP)==ISPOPUP && (m_uiFlags & OLD_POPUP_ID)==OLD_POPUP_ID)
|
|
{
|
|
uiItemID = MAKELONG( 0xFFFF, LOWORD(uiItemID) );
|
|
}
|
|
|
|
// Compare token ID
|
|
if(!((uiTypeID == m_uiTypeID) &&
|
|
(uiResID == m_uiResID) &&
|
|
(uiItemID == m_uiItemID) &&
|
|
(uiFlags == m_uiFlags) &&
|
|
(strItemName == m_strItemName)))
|
|
{
|
|
theApp.WriteCon(CONERR, "Token ID mismatch\t%s\"]]\t%s\"]]\r\n", strSrcTokenID.GetBuffer(0), m_strTokenID.GetBuffer(0));
|
|
theApp.SetReturn(ERROR_RET_TOKEN_MISMATCH);
|
|
return CMainApp::ERR_TOKEN_MISMATCH;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL CToken::GetTgtSize(WORD * px, WORD * py,WORD * pcx, WORD * pcy)
|
|
{
|
|
return sscanf(m_strTgtText, TEXT("%hu %hu %hu %hu"),
|
|
px,
|
|
py,
|
|
pcx,
|
|
pcy);
|
|
}
|
|
|
|
BOOL CToken::GetSrcSize(WORD * px, WORD * py,WORD * pcx, WORD * pcy)
|
|
{
|
|
return sscanf(m_strSrcText, TEXT("%hu %hu %hu %hu"),
|
|
px,
|
|
py,
|
|
pcx,
|
|
pcy);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
CTokenFile::CTokenFile()
|
|
{
|
|
m_Tokens.SetSize(0, 10);
|
|
m_iLastPos = 0;
|
|
m_iUpperBound = -1;
|
|
m_strSrcFile = "";
|
|
m_strTgtFile = "";
|
|
}
|
|
|
|
CTokenFile::~CTokenFile()
|
|
{
|
|
for(INT_PTR at=0; at<=m_iUpperBound; at++)
|
|
delete (m_Tokens.GetAt(at));
|
|
|
|
m_Tokens.RemoveAll();
|
|
}
|
|
|
|
int CTokenFile::Open(CString strSrcFile, CString strTgtFile)
|
|
{
|
|
int iErr = CMainApp::ERR_NOERROR;
|
|
// Open the files
|
|
CStdioFile SrcFile;
|
|
CStdioFile TgtFile;
|
|
|
|
// If we are doing an UPDATE we need both src and tgt files
|
|
// while if we are not it is enough the tgt file.
|
|
// If only the tgt file is given no consistency will be done.
|
|
if(theApp.IsFlag(CMainApp::UPDATE))
|
|
if(!SrcFile.Open(strSrcFile, CFile::modeRead | CFile::shareDenyWrite))
|
|
{
|
|
theApp.WriteCon(CONERR, "Cannot open file: %s\r\n", strSrcFile);
|
|
return CMainApp::ERR_FILE_OPEN;
|
|
}
|
|
|
|
if(!TgtFile.Open(strTgtFile, CFile::modeRead | CFile::shareDenyWrite))
|
|
{
|
|
theApp.WriteCon(CONERR, "Cannot open file: %s\r\n", strTgtFile);
|
|
return CMainApp::ERR_FILE_OPEN;
|
|
}
|
|
|
|
CString strSrc = "";
|
|
CString strTgt = "";
|
|
INT_PTR at;
|
|
|
|
while(TgtFile.ReadString(strTgt.GetBuffer(MAX_TOKEN), MAX_TOKEN))
|
|
{
|
|
if(theApp.IsFlag(CMainApp::UPDATE))
|
|
if(!SrcFile.ReadString(strSrc.GetBuffer(MAX_TOKEN), MAX_TOKEN))
|
|
{
|
|
theApp.WriteCon(CONERR, "The file %s has more tokens than the file %s!\r\n", strTgtFile, strSrcFile);
|
|
theApp.SetReturn(ERROR_RET_TOKEN_MISMATCH);
|
|
return CMainApp::ERR_TOKEN_MISMATCH;
|
|
}
|
|
|
|
strSrc.ReleaseBuffer();
|
|
strTgt.ReleaseBuffer();
|
|
|
|
at = m_Tokens.Add(new CToken());
|
|
|
|
if(iErr = ((CToken*)m_Tokens.GetAt(at))->Parse(strSrc,strTgt))
|
|
{
|
|
goto close;
|
|
}
|
|
|
|
}
|
|
|
|
m_iUpperBound = m_Tokens.GetUpperBound();
|
|
|
|
close:
|
|
if(theApp.IsFlag(CMainApp::UPDATE))
|
|
SrcFile.Close();
|
|
|
|
TgtFile.Close();
|
|
|
|
return iErr;
|
|
}
|
|
|
|
const CToken * CTokenFile::GetTokenSize(CToken * pToken, WORD * px, WORD * py,
|
|
WORD * pcx, WORD * pcy)
|
|
{
|
|
|
|
if((pToken!=NULL) && (pToken->m_uiTypeID!=5))
|
|
return NULL;
|
|
|
|
CToken * pTokenSize = (CToken *)m_Tokens.GetAt(m_iLastPos++);
|
|
|
|
if(pTokenSize==NULL)
|
|
return NULL;
|
|
|
|
WORD x, y, cx, cy;
|
|
pTokenSize->GetSrcSize(&x, &y, &cx, &cy);
|
|
|
|
// check if the size changed
|
|
if(!theApp.IsFlag(CMainApp::UPDATE) ||
|
|
(x==*px &&
|
|
y==*py &&
|
|
cx==*pcx &&
|
|
cy==*pcy) )
|
|
{
|
|
pTokenSize->GetTgtSize(px, py, pcx, pcy);
|
|
}
|
|
else
|
|
{
|
|
theApp.WriteCon(CONWRN, "Item Resized\t%s\"]]\r\n", pTokenSize->m_strTokenID);
|
|
theApp.AddResized();
|
|
}
|
|
|
|
return pTokenSize;
|
|
}
|
|
|
|
const CToken * CTokenFile::GetTokenSize(unsigned int TypeID,
|
|
unsigned int ResID,
|
|
unsigned int ItemID,
|
|
CString strItemName,
|
|
WORD * px, WORD * py,
|
|
WORD * pcx, WORD * pcy)
|
|
{
|
|
if(TypeID!=5)
|
|
return NULL;
|
|
|
|
BOOL bMatch = FALSE;
|
|
|
|
ASSERT(m_iUpperBound!=-1);
|
|
if(m_iLastPos>m_iUpperBound)
|
|
m_iLastPos = 0;
|
|
|
|
CToken * pToken = NULL;
|
|
INT_PTR iLastPos = m_iLastPos;
|
|
|
|
while(!bMatch)
|
|
{
|
|
pToken = (CToken*)m_Tokens.GetAt(m_iLastPos++);
|
|
|
|
if(pToken==NULL)
|
|
return NULL;
|
|
|
|
while(pToken->m_uiTypeID!=TypeID && !bMatch) {
|
|
if(m_iLastPos>m_iUpperBound) {
|
|
m_iLastPos = 0;
|
|
bMatch = TRUE;
|
|
}
|
|
pToken = (CToken*)m_Tokens.GetAt(m_iLastPos++);
|
|
if(pToken==NULL)
|
|
return NULL;
|
|
}
|
|
|
|
// Let's see if we have at least some parameter to find the token
|
|
if(pToken->m_uiTypeID==TypeID &&
|
|
pToken->m_uiResID==ResID &&
|
|
pToken->m_uiItemID==ItemID &&
|
|
pToken->m_strItemName==strItemName &&
|
|
(pToken->m_uiFlags & ISCOR)) // to be compatible with rlman token ids
|
|
{
|
|
WORD x, y, cx, cy;
|
|
pToken->GetSrcSize(&x, &y, &cx, &cy);
|
|
|
|
// check if the size changed
|
|
if(!theApp.IsFlag(CMainApp::UPDATE) ||
|
|
(x==*px &&
|
|
y==*py &&
|
|
cx==*pcx &&
|
|
cy==*pcy) )
|
|
{
|
|
pToken->GetTgtSize(px, py, pcx, pcy);
|
|
}
|
|
else
|
|
{
|
|
theApp.WriteCon(CONWRN, "Item Resized\t%s\"]]\r\n", pToken->m_strTokenID);
|
|
theApp.AddResized();
|
|
}
|
|
|
|
return pToken;
|
|
}
|
|
else if(pToken->m_uiTypeID!=TypeID)
|
|
{
|
|
m_iLastPos = iLastPos;
|
|
return NULL;
|
|
}
|
|
|
|
if(m_iLastPos>m_iUpperBound)
|
|
return NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const CToken * CTokenFile::GetToken(unsigned int TypeID,
|
|
unsigned int ResID,
|
|
unsigned int ItemID,
|
|
CString strText,
|
|
CString strItemName)
|
|
{
|
|
if(strText.IsEmpty() && (TypeID != 5L)) // Allow Dialog Strings to be NULL
|
|
return NULL;
|
|
|
|
BOOL bMatch = FALSE;
|
|
|
|
ASSERT(m_iUpperBound!=-1);
|
|
if(m_iLastPos>m_iUpperBound)
|
|
m_iLastPos = 0;
|
|
|
|
CToken * pToken = NULL;
|
|
INT_PTR iLastPos = m_iLastPos;
|
|
|
|
while(!bMatch)
|
|
{
|
|
pToken = (CToken*)m_Tokens.GetAt(m_iLastPos++);
|
|
|
|
if(pToken==NULL)
|
|
return NULL;
|
|
|
|
while(pToken->m_uiTypeID!=TypeID && !bMatch) {
|
|
if(m_iLastPos>m_iUpperBound) {
|
|
m_iLastPos = 0;
|
|
bMatch = TRUE;
|
|
}
|
|
pToken = (CToken*)m_Tokens.GetAt(m_iLastPos++);
|
|
if(pToken==NULL)
|
|
return NULL;
|
|
}
|
|
|
|
// Let's see if we have at least some parameter to find the token
|
|
if(pToken->m_uiTypeID==TypeID &&
|
|
pToken->m_uiResID==ResID &&
|
|
pToken->m_uiItemID==ItemID &&
|
|
pToken->m_strItemName==strItemName &&
|
|
!(pToken->m_uiFlags & ISCOR)) // to be compatible with rlman token ids
|
|
{
|
|
if(!theApp.IsFlag(CMainApp::FONTS) && (pToken->m_uiFlags & ISDLGFONTNAME) || (pToken->m_uiFlags & ISDLGFONTSIZE))
|
|
return pToken;
|
|
else if(!theApp.IsFlag(CMainApp::UPDATE) || pToken->m_strSrcText==strText)
|
|
return pToken;
|
|
else
|
|
{
|
|
theApp.WriteCon(CONWRN, "Context changed\t%s\"]]\r\n", pToken->m_strTokenID);
|
|
theApp.AddChanged();
|
|
pToken->m_uiLastError = 1;
|
|
return pToken;
|
|
}
|
|
}
|
|
else if(pToken->m_uiTypeID!=TypeID) {
|
|
m_iLastPos = iLastPos;
|
|
return NULL;
|
|
}
|
|
|
|
if(m_iLastPos>m_iUpperBound)
|
|
return NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const CToken * CTokenFile::GetNoCaptionToken(unsigned int TypeID,
|
|
unsigned int ResID,
|
|
unsigned int ItemID,
|
|
CString strItemName)
|
|
{
|
|
BOOL bMatch = FALSE;
|
|
|
|
ASSERT(m_iUpperBound!=-1);
|
|
if(m_iLastPos>m_iUpperBound)
|
|
m_iLastPos = 0;
|
|
|
|
CToken * pToken = NULL;
|
|
INT_PTR iLastPos = m_iLastPos;
|
|
|
|
while(!bMatch)
|
|
{
|
|
pToken = (CToken*)m_Tokens.GetAt(m_iLastPos++);
|
|
|
|
if(pToken==NULL)
|
|
return NULL;
|
|
|
|
while(pToken->m_uiTypeID!=TypeID && !bMatch) {
|
|
if(m_iLastPos>m_iUpperBound) {
|
|
m_iLastPos = 0;
|
|
bMatch = TRUE;
|
|
}
|
|
pToken = (CToken*)m_Tokens.GetAt(m_iLastPos++);
|
|
if(pToken==NULL)
|
|
return NULL;
|
|
}
|
|
|
|
// Let's see if we have at least some parameter to find the token
|
|
if(pToken->m_uiTypeID==TypeID &&
|
|
pToken->m_uiResID==ResID &&
|
|
pToken->m_uiItemID==ItemID &&
|
|
pToken->m_strItemName==strItemName && // to be compatible with rlman token ids
|
|
(!pToken->m_strSrcText || TypeID !=4)) // Some binaries like shell32.dll uses the same id 0 as MENU SEPARATOR. Filter those out.
|
|
{
|
|
return pToken;
|
|
}
|
|
else if(pToken->m_uiTypeID!=TypeID) {
|
|
m_iLastPos = iLastPos;
|
|
return NULL;
|
|
}
|
|
|
|
if(m_iLastPos>m_iUpperBound)
|
|
return NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|