//////////////////////////////////////// // 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; }