2579 lines
49 KiB
C++

/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// BabylonDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Babylon.h"
#include "BabylonDlg.h"
#include "VIEWDBSII.h"
#include "verifydlg.h"
#include "exportdlg.h"
#include "report.h"
#include "matchdlg.h"
#include "retranslatedlg.h"
#include "generatedlg.h"
#include "DlgProxy.h"
#include "xlstuff.h"
#include "fileops.h"
#include <time.h>
#include "iff.h"
#include "loadsave.h"
#include "expimp.h"
#include "proceeddlg.h"
#include "transcs.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static char buffer[100*1024];
static char buffer2[100*1024];
static char buffer3[100*1024];
static const int INCREMENTS = 100;
static const int MAX_INFO_LEN = 2*1024;
static int found_error;
static int cb_count;
static CBabylonDlg *mainDlg;
static void print_to_log ( const char *text )
{
if ( !found_error )
{
mainDlg->Log ("FAILED", SAME_LINE );
found_error = TRUE;
}
sprintf ( buffer, "String %s", text);
mainDlg->Log ( buffer );
}
static void print_to_log_and_update_progress ( const char *text )
{
print_to_log ( text );
cb_count++;
mainDlg->SetProgress ( cb_count );
}
static void cb_progress ( void )
{
cb_count++;
mainDlg->SetProgress ( cb_count );
}
typedef struct
{
char comment[MAX_INFO_LEN+1];
char context[MAX_INFO_LEN+1];
char speaker[MAX_INFO_LEN+1];
char listener[MAX_INFO_LEN+1];
char wave[MAX_INFO_LEN+1];
int maxlen;
} INFO;
static INFO global_info;
static INFO local_info;
static void init_info ( INFO *info )
{
info->comment[0] = 0;
info->context[0] = 0;
info->speaker[0] = 0;
info->listener[0] = 0;
info->wave[0] = 0;
info->maxlen = 0;
}
static int progress_count;
static void progress_cb ( void )
{
progress_count++;
if ( MainDLG )
{
MainDLG->SetProgress ( progress_count );
}
}
static void removeLeadingAndTrailing ( char *buffer )
{
char *first, *ptr;
char ch;
ptr = first = buffer;
while ( (ch = *first) && iswspace ( ch ))
{
first++;
}
while ( *ptr++ = *first++ );
ptr -= 2;;
while ( (ptr > buffer) && (ch = *ptr) && iswspace ( ch ) )
{
ptr--;
}
ptr++;
*ptr = 0;
}
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
virtual BOOL OnInitDialog();
afx_msg void OnButton1();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBabylonDlg dialog
IMPLEMENT_DYNAMIC(CBabylonDlg, CDialog);
CBabylonDlg::CBabylonDlg(CWnd* pParent /*=NULL*/)
: CDialog(CBabylonDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CBabylonDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pAutoProxy = NULL;
}
CBabylonDlg::~CBabylonDlg()
{
// If there is an automation proxy for this dialog, set
// its back pointer to this dialog to NULL, so it knows
// the dialog has been deleted.
if (m_pAutoProxy != NULL)
m_pAutoProxy->m_pDialog = NULL;
}
void CBabylonDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CBabylonDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CBabylonDlg, CDialog)
//{{AFX_MSG_MAP(CBabylonDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_CLOSE()
ON_WM_DROPFILES()
ON_BN_CLICKED(IDC_VIEWDBS, OnViewdbs)
ON_BN_CLICKED(IDC_RELOAD, OnReload)
ON_BN_CLICKED(IDC_UPDATE, OnUpdate)
ON_BN_CLICKED(IDC_SAVE, OnSave)
ON_BN_CLICKED(IDC_WARNINGS, OnWarnings)
ON_BN_CLICKED(IDC_ERRORS, OnErrors)
ON_BN_CLICKED(IDC_CHANGES, OnChanges)
ON_BN_CLICKED(IDC_EXPORT, OnExport)
ON_BN_CLICKED(IDC_IMPORT, OnImport)
ON_BN_CLICKED(IDC_GENERATE, OnGenerate)
ON_BN_CLICKED(IDC_DIALOG, OnVerifyDialog)
ON_BN_CLICKED(IDC_TRANSLATIONS, OnTranslations)
ON_CBN_SELCHANGE(IDC_COMBOLANG, OnSelchangeCombolang)
ON_BN_CLICKED(IDC_REPORTS, OnReports)
ON_CBN_DBLCLK(IDC_COMBOLANG, OnDblclkCombolang)
ON_BN_CLICKED(IDC_RESET, OnReset)
ON_BN_CLICKED(IDC_SENT, OnSent)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBabylonDlg message handlers
BOOL CBabylonDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
progress = (CProgressCtrl *) GetDlgItem ( IDC_PROGRESS1 );
percent = (CStatic *) GetDlgItem ( IDC_PERCENT );
SetWindowText ( AppTitle );
Log ( AppTitle );
{
char buffer[100];
char date[50];
char time[50];
_strtime ( time );
_strdate ( date );
sprintf ( buffer, "Session Date: %s %s\n", date, time);
Log ( buffer );
}
Status ("Initializing dialog");
operate_always = FALSE;
combo = ( CComboBox *)GetDlgItem ( IDC_COMBOLANG );
int index = 0;
int lang_index = 0;
LANGINFO *info;
while ( (info = GetLangInfo ( lang_index )) )
{
combo->InsertString ( index, info->name );
combo->SetItemDataPtr ( index, info );
index++;
lang_index++;
}
max_index = index;
combo->SetCurSel ( 0 );
// do any initialization
#if 0
// initialize audio
if ( !AIL_quick_startup ( TRUE, FALSE, 22050, 16, 2 ) )
{
sprintf ( buffer, "Falied to init audio.\n\nReason:%s\n", AIL_last_error ());
AfxMessageBox ( buffer );
}
else
{
onexit ( (_onexit_t ) AIL_quick_shutdown );
}
#endif
Ready();;
PostMessage ( WM_COMMAND, MAKEWPARAM ( IDC_RELOAD, BN_CLICKED ));
return TRUE; // return TRUE unless you set the focus to a control
}
void CBabylonDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CBabylonDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CBabylonDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
// Automation servers should not exit when a user closes the UI
// if a controller still holds on to one of its objects. These
// message handlers make sure that if the proxy is still in use,
// then the UI is hidden but the dialog remains around if it
// is dismissed.
void CBabylonDlg::OnClose()
{
if (CanExit())
{
if ( !CanProceed ())
{
return ;
}
CDialog::OnOK();
if ( !SaveLog () )
{
AfxMessageBox ("Failed to save log!\n\nMake sure babylon.log is writable");
}
}
}
//DEL void CBabylonDlg::OnOK()
//DEL {
//DEL if (CanExit())
//DEL CDialog::OnOK();
//DEL }
//DEL void CBabylonDlg::OnCancel()
//DEL {
//DEL if (CanExit())
//DEL CDialog::OnCancel();
//DEL }
BOOL CBabylonDlg::CanExit()
{
// If the proxy object is still around, then the automation
// controller is still holding on to this application. Leave
// the dialog around, but hide its UI.
if (m_pAutoProxy != NULL)
{
ShowWindow(SW_HIDE);
return FALSE;
}
return TRUE;
}
//DEL void CBabylonDlg::OnBrowse()
//DEL {
//DEL static char szFilter[] = "XL Files (*.XLS)\0*.xls\0\0\0";
//DEL
//DEL // TODO: Add your control notification handler code here
//DEL CFileDialog *dlg = new CFileDialog ( TRUE, "xls", "*.xls", OFN_FILEMUSTEXIST, szFilter, this );
//DEL if ( dlg )
//DEL {
//DEL dlg->DoModal ();
//DEL if ( dlg->GetPathName() != "*.xls" )
//DEL {
//DEL SelectFile ( LPCTSTR ( dlg->GetPathName() ));
//DEL }
//DEL else
//DEL {
//DEL SelectFile ( NULL );
//DEL }
//DEL delete dlg;
//DEL }
//DEL }
//DEL void CBabylonDlg::OnChangeXlFilename()
//DEL {
//DEL // TODO: If this is a RICHEDIT control, the control will not
//DEL // send this notification unless you override the CDialog::OnInitDialog()
//DEL // function and call CRichEditCtrl().SetEventMask()
//DEL // with the ENM_CHANGE flag ORed into the mask.
//DEL
//DEL // TODO: Add your control notification handler code here
//DEL
//DEL }
void CBabylonDlg::OnExport()
{
if ( CanOperate ())
{
CExportDlg dlg;
if ( dlg.DoModal () == IDOK )
{
ExportTranslations ( MainDB, dlg.Filename (), dlg.Language(), dlg.Options(), this );
}
}
}
BOOL CAboutDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
char string[200];
sprintf ( string, "Built: %s, %s", __DATE__, __TIME__ );
SetDlgItemText ( IDC_BUILD, string );
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CBabylonDlg::OnDropFiles(HDROP hDropInfo)
{
// TODO: Add your message handler code here and/or call default
// char buffer[1024];
//
// if ( DragQueryFile(hDropInfo, 0, buffer, sizeof ( buffer )-1))
// {
//
// if ( ConvertStrFile ( buffer ) )
// {
// return;
// }
//
// if ( SelectFile ( buffer ) )
// {
// OnExport ();
// }
// }
}
//DEL int CBabylonDlg::SelectFile ( const char *buffer )
//DEL {
//DEL char *p;
//DEL CWnd *wnd = GetDlgItem ( IDC_EXPORT );
//DEL
//DEL if ( buffer && (p = strchr ( buffer, '.' )) && !stricmp ( p, ".xls"))
//DEL {
//DEL SetDlgItemText ( IDC_XLFILE, buffer );
//DEL SetDlgItemText ( IDC_STATUS, "File selected: Click 'convert' to start process");
//DEL wnd->EnableWindow ( TRUE );
//DEL return TRUE;
//DEL }
//DEL if ( buffer )
//DEL {
//DEL AfxMessageBox ("Must be an Excel file");
//DEL }
//DEL wnd->EnableWindow ( FALSE );
//DEL SetDlgItemText ( IDC_STATUS, "Select excel file...");
//DEL SetDlgItemText ( IDC_XLFILE, "Browse or drop excel file to be convertered" );
//DEL
//DEL return FALSE;
//DEL }
//DEL int CBabylonDlg::ConvertStrFile ( const char *buffer )
//DEL {
//DEL char *p;
//DEL char filename[400];
//DEL
//DEL if ( buffer && (p = strchr ( buffer, '.' )) && !stricmp ( p, ".str"))
//DEL {
//DEL ParseDB db;
//DEL SetDlgItemText ( IDC_XLFILE, buffer );
//DEL EnableWindow ( FALSE );
//DEL SetDlgItemText ( IDC_STATUS, "Parsing .str file");
//DEL
//DEL if ( db.ParseStrFile ( buffer, this ) )
//DEL {
//DEL SetDlgItemText ( IDC_STATUS, "Creating .xls file");
//DEL strcpy ( filename, buffer );
//DEL p = strchr ( filename, '.' );
//DEL strcpy ( p, ".xls" );
//DEL
//DEL if ( db.CreateXLFile ( filename, this ) )
//DEL {
//DEL SetDlgItemText ( IDC_STATUS, "Created .xls file");
//DEL }
//DEL else
//DEL {
//DEL SetDlgItemText ( IDC_STATUS, "Falied to create .xls file");
//DEL }
//DEL
//DEL }
//DEL else
//DEL {
//DEL SetDlgItemText ( IDC_STATUS, "Failed to parse .str file");
//DEL
//DEL }
//DEL
//DEL EnableWindow ( TRUE );
//DEL return TRUE;
//DEL }
//DEL return FALSE;
//DEL }
static int bytes_copied;
static int done_copy;
static int start_copy;
static LogFormat cpy_format;
static DWORD CALLBACK streamin_cb ( DWORD dwCookie, LPBYTE pbBuff, LONG bytes, LONG *transfered )
{
char *src = (char *) dwCookie;
int count = 0;
src += bytes_copied;
if ( bytes && start_copy )
{
if ( cpy_format == NEW_LINE )
{
*pbBuff++ = '\n';
count++;
bytes--;
}
start_copy = FALSE;
}
while ( bytes-- )
{
if ( !*src )
{
done_copy = TRUE;
break;
}
*pbBuff++ = *src++;
bytes_copied++;
count++;
}
*transfered = count;
return 0;
}
static DWORD CALLBACK streamout_cb ( DWORD dwCookie, LPBYTE pbBuff, LONG bytes, LONG *transfered )
{
FILE *log = (FILE *) dwCookie;
int count = 0;
*transfered = fwrite ( pbBuff, 1, bytes, log );
return *transfered == -1;
}
void CBabylonDlg::Log( const char *string, LogFormat format)
{
CRichEditCtrl *rec;
EDITSTREAM es;
int lines;
int end_pos;
rec = (CRichEditCtrl*)GetDlgItem ( IDC_LOG );
lines = rec->GetLineCount ( );
end_pos = rec->LineIndex ( lines );
rec->SetSel ( end_pos, end_pos );
//rec->SetReadOnly ( FALSE );
es.dwCookie = (DWORD) string;
es.dwError = 0;
es.pfnCallback = streamin_cb;
bytes_copied = 0;
done_copy = FALSE;
start_copy = TRUE;
cpy_format = format;
rec->StreamIn ( SF_TEXT | SFF_SELECTION, es );
//rec->SetReadOnly ( TRUE );
lines = rec->GetLineCount ( );
rec->LineScroll ( -lines, 0 );
rec->LineScroll ( lines - 10, 0 );
}
void CBabylonDlg::Status( const char *string, int log )
{
char buffer[200];
int max_len;
if ( log )
{
Log ( string );
}
max_len = sizeof ( buffer ) -1;
strcpy ( buffer, "Status: ");
max_len -= strlen ( buffer );
strncat ( buffer, string, max_len );
SetDlgItemText ( IDC_STATUS, buffer );
}
int CBabylonDlg::SaveLog()
{
FILE *log = NULL;
EDITSTREAM es;
CRichEditCtrl *rec = (CRichEditCtrl *) GetDlgItem ( IDC_LOG );
int ok = FALSE;
if ( ! (log = fopen ("babylon.log", "a+t" )))
{
goto error;
}
{
char *buffer = "\nLOG START ******************\n\n";
fwrite ( buffer, 1, strlen ( buffer ), log );
}
es.dwCookie = (DWORD) log;
es.dwError = 0;
es.pfnCallback = streamout_cb;
bytes_copied = 0;
done_copy = FALSE;
rec->StreamOut ( SF_TEXT, es );
if ( es.dwError )
{
goto error;
}
{
char *buffer = "\nQuiting Babylon\n\nLOG END ******************\n\n";
fwrite ( buffer, 1, strlen ( buffer ), log );
}
ok = TRUE;
error:
if ( log )
{
fclose ( log );
}
return ok;
}
void CBabylonDlg::OnViewdbs()
{
// TODO: Add your control notification handler code here
VIEWDBSII dlg;
ViewChanges = FALSE;
dlg.DoModal ();
}
static int readToEndOfQuote( FILE *file, char *in, char *out, char *wavefile, int maxBufLen, int in_comment )
{
int slash = FALSE;
int state = 0;
int line_start = FALSE;
char ch;
int new_lines = 0;
int ccount = 0;
while ( maxBufLen )
{
// get next char
if ( in )
{
if ( !(ch = *in++))
{
in = NULL; // have exhausted the input buffer
ch = getc ( file );
}
}
else
{
ch = getc ( file );
}
if ( ch == EOF )
{
AfxMessageBox ( "Missing terminating quote");
return new_lines;
}
if ( ch == '\n' )
{
line_start = TRUE;
if ( !in )
{
new_lines++;
}
slash = FALSE;
ccount = 0;
ch = ' ';
}
else if ( line_start && ( ch == '/' || iswspace ( ch )) )
{
continue;
}
else if ( ch == '\\' && !slash)
{
slash = TRUE;
}
else if ( ch == '\\' && slash)
{
slash = FALSE;
}
else if ( ch == '"' && !slash )
{
break; // done
}
else
{
slash = FALSE;
}
if ( iswspace ( ch ))
{
ch = ' ';
}
else
{
line_start = FALSE;
}
*out++ = ch;
maxBufLen--;
}
*out = 0;
if ( !wavefile )
{
return new_lines;
}
int len = 0;
while ( TRUE )
{
// get next char
if ( in )
{
if ( !(ch = *in++))
{
in = NULL; // have exhausted the input buffer
ch = getc ( file );
}
}
else
{
ch = getc ( file );
}
if ( ch == '\n' || ch == EOF )
{
if ( !in )
{
new_lines++;
}
break;
}
switch ( state )
{
case 0:
if ( iswspace ( ch ) || ch == '=' )
{
break;
}
state = 1;
case 1:
if ( (( ch >= 'a' && ch <= 'z') || ( ch >= 'A' && ch <='Z') || (ch >= '0' && ch <= '9') || ch == '_') )
{
*wavefile++ = ch;
len++;
break;
}
state = 2;
case 2:
break;
}
}
*wavefile = 0;
if ( len )
{
if ( ( ch = *(wavefile-1)) < '0' || ch > '9' )
{
// remove last character
*(wavefile-1) = 0;
}
}
return new_lines;
}
enum
{
START,
TOKEN,
COLON,
ARG
};
static int getString ( FILE *file, char *in, char *out )
{
int bytes = MAX_INFO_LEN;
int new_lines = 0;
char ch;
char *ptr = out;
{
while ( (ch = *in++) && ch != '\n' && bytes )
{
*ptr++ = ch;
bytes--;
}
}
*ptr = 0;
ConvertMetaChars ( out );
StripSpaces ( out );
return new_lines;
}
static char *getToken ( char *buffer, char *token, int bytes )
{
char ch;
int state = START;
*token = 0;
while ( (ch = *buffer) && ch != '\n' && bytes )
{
switch ( state )
{
case START:
if ( ch == '/' || iswspace ( ch ))
{
break;
}
state = TOKEN;
case TOKEN:
if ( !iswspace ( ch ) && ch !=':' )
{
*token++ = ch;
bytes--;
break;
}
*token = 0;
state = COLON;
case COLON:
if ( ch != ':' )
{
break;
}
state = ARG;
break;
case ARG:
if ( iswspace ( ch ) )
{
break;
}
return buffer;
}
buffer++;
}
*token = 0;
return buffer;
}
static int parseComment ( FILE *file, char *buffer, INFO *info )
{
char token[256];
int new_lines = 0;
buffer = getToken ( buffer, token, sizeof (token) -1 );
if ( !token )
{
return new_lines;
}
if ( !stricmp ( token, "COMMENT" ) )
{
new_lines += getString ( file, buffer, info->comment );
}
else if ( !stricmp ( token, "CONTEXT" ) )
{
new_lines += getString ( file, buffer, info->context );
}
else if ( !stricmp ( token, "SPEAKER" ) )
{
new_lines += getString ( file, buffer, info->speaker );
}
else if ( !stricmp ( token, "LISTENER" ) )
{
new_lines += getString ( file, buffer, info->listener );
}
else if ( !stricmp ( token, "MAXLEN" ) )
{
info->maxlen = atoi ( buffer );
}
else if ( !stricmp ( token, "WAVE" ) )
{
new_lines += getString ( file, buffer, info->wave );
}
return new_lines;
}
static int getLabelCount( char *filename )
{
int count = 0;
FILE *fp;
if ( ! ( fp = fopen ( filename, "rt" )))
{
return 0;
}
while(TRUE)
{
if( fscanf( fp, "%s", buffer ) == EOF )
break;
if ( !stricmp( buffer, "END" ) )
{
count++;
}
}
fclose ( fp );
return count;
}
int CBabylonDlg::LoadStrFile ( TransDB *db, const char *filename, void (*cb) ( void ) )
{
FILE *file = NULL;
BabylonLabel *label = NULL;
int status = FALSE;
int line_number = 0;
int label_count = 0;
int text_dup_count = 0;
int label_dup_count = 0;
init_info ( &global_info );
if ( !(file = fopen ( filename, "rt" ) ))
{
goto exit;
}
while ( fgets ( buffer, sizeof(buffer)-1, file ) )
{
line_number++;
removeLeadingAndTrailing ( buffer );
if ( !buffer[0] || (buffer[0] == '/' && buffer[1] == '/') )
{
line_number += parseComment ( file, buffer, &global_info );
continue;
}
label = new BabylonLabel ( );
label->SetName ( buffer );
label->LockName ();
label->SetLineNumber ( line_number );
db->AddLabel ( label );
local_info = global_info;
local_info.wave[0] = 0; // wave file name is only locally set
while( TRUE )
{
if ( !fgets ( buffer, sizeof(buffer)-1, file ))
{
AfxMessageBox ( "Unexpected end of file" );
goto exit;
}
line_number++;
removeLeadingAndTrailing ( buffer );
if ( !stricmp ( buffer, "END" ) )
{
break;
}
if ( !buffer[0] || (buffer[0] == '/' && buffer[1] == '/') )
{
line_number += parseComment ( file, buffer, &local_info );
continue;
}
if ( buffer[0] == '"' )
{
int line = line_number;
strcat ( buffer, "\n" );
line_number += readToEndOfQuote( file, &buffer[1], buffer2, buffer3, sizeof(buffer2)-1, FALSE );
BabylonText *text = new BabylonText ( );
text->Set ( buffer2 );
text->FormatMetaString ();
text->LockText ();
if ( buffer3[0] )
{
text->SetWave ( buffer3 );
}
else
{
text->SetWave ( local_info.wave );
}
text->SetLineNumber ( line );
label->AddText ( text );
}
}
label->SetComment ( local_info.comment );
label->SetContext ( local_info.context );
label->SetSpeaker ( local_info.speaker );
label->SetListener ( local_info.listener );
label->SetMaxLen ( local_info.maxlen );
if ( cb )
{
cb ();
}
label = NULL;
}
status = TRUE;
exit:
db->ClearChanges ();
if ( label )
{
delete label;
}
if ( file )
{
fclose ( file );
}
return status;
}
int CBabylonDlg::CanProceed ( void )
{
if ( MainDB->IsChanged ())
{
retry:
int result = AfxMessageBox ( "Main database has changed!\n\n Do you wish to save it before proceeding?", MB_YESNOCANCEL );
if ( result == IDCANCEL )
{
return FALSE;
}
else if ( result == IDYES )
{
if ( !SaveMainDB () )
{
AfxMessageBox ("Save failed!\n\nCanceling operation");
return FALSE;
}
}
else
{
int result = AfxMessageBox ( "Are you sure you don't want to save?\n\nAll current changes will be lost", MB_YESNO );
if ( result == IDNO )
{
goto retry;
}
}
}
return TRUE;
}
int CBabylonDlg::CanOperate ( void )
{
if ( operate_always )
{
return TRUE;
}
if ( BabylonstrDB->IsChanged() || BabylonstrDB->HasErrors () )
{
char *string = "Unknown problem!\n\n\nProceed anyway?";
if ( BabylonstrDB->HasErrors ())
{
string = "Generals.str has errors! As a result the translation database is not up to date!\n\nRecommend you fix problems in Generals.str before proceeding.\n\n\n\nDo you wish to continue anyway?";
}
if ( BabylonstrDB->IsChanged ())
{
string = "The translation database is not up to date! Generals.str has changed since the last time the database was updated.\n\nRecommend you update the database before proceeding.\n\n\n\nDo you wish to continue anyway?";
}
ProceedDlg dlg ( string );
int result = dlg.DoModal ();
if ( result == IDALWAYS )
{
operate_always = TRUE;
}
return result != IDNO;
}
return TRUE;
}
void CBabylonDlg::OnReload()
{
int num_errors;
int num_warnings;
int count = 0;
int str_loaded = FALSE;
int db_loaded = FALSE;
int db_readonly = FALSE;
int db_error = FALSE;
int do_update = FALSE;
int errors;
CWnd *win;
// TODO: Add your control notification handler code here
if ( !CanProceed ())
{
return;
}
BabylonstrDB->Clear ();
BabylonstrDB->ClearChanges ();
MainDB->Clear ();
MainDB->ClearChanges ();
count += getLabelCount ( BabylonstrFilename );
count += GetLabelCountDB ( MainXLSFilename );
progress_count = 0;
win = GetDlgItem ( IDC_ERRORS );
win->EnableWindow ( FALSE );
win = GetDlgItem ( IDC_WARNINGS );
win->EnableWindow ( FALSE );
win = GetDlgItem ( IDC_UPDATE );
win->EnableWindow ( TRUE);
win = GetDlgItem ( IDC_SAVE );
win->EnableWindow ( TRUE);
win = GetDlgItem ( IDC_IMPORT );
win->EnableWindow ( TRUE);
win = GetDlgItem ( IDC_EXPORT );
win->EnableWindow ( TRUE);
InitProgress ( count );
Log ("" );
if ( FileExists ( BabylonstrFilename ))
{
if ( (errors = ValidateStrFile ( BabylonstrFilename )) )
{
if ( errors == -1 )
{
if ( AfxMessageBox ( "Unable to verify string file!\n\nMake sure \"strcheck.exe\" is in your path and \"strcheck.rst\" is writeable.\n\nDo you wish to continue loading? \n\nWarning: Any errors in the string file could cause inappropiate updates to the database.", MB_YESNO ) == IDYES )
{
errors = 0;
}
}
else
{
sprintf ( buffer, "\"%s\" has %d formating error%s!\n\nFile will not be loaded.", BabylonstrFilename, errors, errors == 1 ? "" : "s" );
AfxMessageBox ( buffer );
}
}
if ( !errors )
{
sprintf ( buffer, "Loading \"%s\"...", BabylonstrFilename );
Status ( buffer );
if ( !(str_loaded = LoadStrFile ( BabylonstrDB, BabylonstrFilename, progress_cb )) )
{
Log ( "FAILED", SAME_LINE );
BabylonstrDB->Clear ();
BabylonstrDB->ClearChanges ();
}
}
else
{
sprintf ( buffer, "Loading \"%s\"...NOT LOADED", BabylonstrFilename );
Log ( buffer );
}
}
else
{
sprintf ( buffer, "Loading \"%s\"...", BabylonstrFilename );
Status ( buffer );
Log ( "FILE NOT FOUND", SAME_LINE );
}
if ( str_loaded )
{
sprintf ( buffer, "Validating \"%s\"...", BabylonstrFilename );
Status ( buffer, FALSE );
if ( (num_errors = BabylonstrDB->Errors ( )))
{
sprintf ( buffer, "Generals.str has %d error(s):\n\nClick \"Errors\" for a detailed list.\n\nAll errors must be fixed before \"Update\" will be enabled.", num_errors );
AfxMessageBox ( buffer );
win = GetDlgItem ( IDC_UPDATE );
win->EnableWindow ( FALSE);
win = GetDlgItem ( IDC_ERRORS );
win->EnableWindow ( TRUE );
}
if ( (num_warnings = BabylonstrDB->Warnings()))
{
win = GetDlgItem ( IDC_WARNINGS );
win->EnableWindow ( TRUE );
}
if ( !num_errors && !num_warnings )
{
Log ( "OK", SAME_LINE );
}
else
{
sprintf ( buffer, "%d errors, %d warnings OK", num_errors, num_warnings );
Log ( buffer, SAME_LINE );
}
}
sprintf ( buffer, "Loading \"%s\"...", MainXLSFilename );
Status ( buffer );
if ( FileExists ( MainXLSFilename ))
{
if ( !(db_loaded = LoadMainDB ( MainDB, MainXLSFilename, progress_cb )) )
{
Log ( "FAILED", SAME_LINE );
MainDB->Clear ();
MainDB->ClearChanges ();
db_error = TRUE;
win = GetDlgItem ( IDC_UPDATE );
win->EnableWindow ( FALSE);
win = GetDlgItem ( IDC_SAVE );
win->EnableWindow ( FALSE);
win = GetDlgItem ( IDC_EXPORT );
win->EnableWindow ( FALSE);
win = GetDlgItem ( IDC_IMPORT );
win->EnableWindow ( FALSE);
}
else
{
if ( FileAttribs ( MainXLSFilename ) & FA_READONLY )
{
AfxMessageBox ( "Database file is readonly!\n\nNo updates will be allowed.\n\nCheckout the database file and reload.");
db_readonly = TRUE;
win = GetDlgItem ( IDC_UPDATE );
win->EnableWindow ( FALSE);
win = GetDlgItem ( IDC_SAVE );
win->EnableWindow ( FALSE);
win = GetDlgItem ( IDC_IMPORT );
win->EnableWindow ( FALSE);
Log ( "READONLY", SAME_LINE );
}
else
{
Log ( "OK", SAME_LINE );
}
}
}
else
{
Log ( "FILE NOT FOUND", SAME_LINE );
}
if ( str_loaded && !db_error && !num_errors )
{
if ( UpdateDB ( BabylonstrDB, MainDB, FALSE ) )
{
BabylonstrDB->Changed ();
if ( db_loaded )
{
if ( db_readonly )
{
sprintf ( buffer, "\"%s\" has changed!\n\nHowever, as the database is READ ONLY you cannot update the changes.", BabylonstrFilename);
}
else
{
sprintf ( buffer, "\"%s\" has changed!\n\nRecomended that you update the database with these new changes.\n\nDo you wish to update now?", BabylonstrFilename);
}
}
else
{
sprintf ( buffer, "New Database!\n\nRecomended that you update the new database.\n\nDo you wish to update now?", BabylonstrFilename);
}
if ( db_readonly )
{
do_update = FALSE;
AfxMessageBox ( buffer );
}
else
{
do_update = (AfxMessageBox ( buffer, MB_YESNO ) == IDYES);
}
}
}
ProgressComplete ();
Ready ();
if ( do_update )
{
OnUpdate ();
}
}
void CBabylonDlg::InitProgress(int range)
{
if ( (progress_range = range) <= 0 )
{
progress_range = 1;
}
progress->SetRange ( 0, INCREMENTS );
progress_pos = -1;
progress->SetPos ( 0 );
}
void CBabylonDlg::SetProgress(int pos)
{
char string[20];
int new_pos = (pos * 100 ) / progress_range;
if ( new_pos > 100 )
{
new_pos = 100;
}
else if ( new_pos < 0 )
{
new_pos = 0;
}
if ( new_pos == progress_pos )
{
return;
}
progress->SetPos ( new_pos );
progress_pos = new_pos;
sprintf ( string, "%d%% ", progress_pos );
percent->SetWindowText ( string );
}
void CBabylonDlg::ProgressComplete()
{
progress->SetPos ( 100 );
percent->SetWindowText ( "100% ");
}
void CBabylonDlg::OnUpdate()
{
// TODO: Add your control notification handler code here
UpdateDB ( BabylonstrDB, MainDB );
}
#define MACRO_UPDATE(field,count) { if ( wcsicmp ( source->##field () , destination->##field ())) \
{ \
if ( update ) \
{ \
destination->Set##field ( source->##field () ); \
} \
label_modified = TRUE; \
info.changes++; \
(count)++; \
} \
}
int CBabylonDlg::UpdateLabel( BabylonLabel *source, BabylonLabel *destination, UPDATEINFO &info, int update, int skip )
{
BabylonText *stext, *dtext;
ListSearch sh;
TransDB *destDB, *srcDB;
int label_modified = FALSE;
destination->ClearMatched ();
source->ClearMatched ();
destDB = destination->DB();
srcDB = source->DB ();
// first go through and match up as many strings as possible
stext = source->FirstText ( sh );
while ( stext )
{
dtext = destDB->FindText ( stext->Get ());
// remember FindText() spans labels so keep looking till we find
// one that belongs to the label we are checking
while ( dtext && (dtext->Label () != destination) )
{
dtext = destDB->FindNextText ();
}
if ( dtext && dtext->Matched ())
{
AfxMessageBox ( "Fatal error: substring already matched" );
return FALSE;
}
if ( dtext )
{
// we have a matching string so mark it
dtext->Match ( stext );
stext->Match ( dtext );
}
stext = source->NextText ( sh );
}
// ask the user to resolve remaing unmatched strings
{
stext = source->FirstText ( sh );
while ( stext )
{
if ( destination->AllMatched ())
{
// no point trying to match anymore
break;
}
if ( !stext->Matched () )
{
int result;
BabylonText *match = NULL;
if ( update && !skip )
{
if ( destination->DB()->MultiTextAllowed())
{
result = MatchText ( stext, destination, &match );
}
else
{
ListSearch tsh;
BabylonText *oldtext = destination->FirstText ( tsh );
if ( !oldtext )
{
break;
}
result = RetranslateText ( stext, oldtext );
match = oldtext;
}
}
else
{
result = IDSKIP;
}
if ( result == IDCANCEL || result == IDSKIP)
{
return result;
}
if ( match )
{
stext->Match ( match );
match->Match ( stext );
}
stext->Processed ();
}
stext = source->NextText ( sh );
}
}
// go through all matched strings and update them accordingly
dtext = destination->FirstText ( sh );
while ( dtext )
{
if ( (stext = (BabylonText *) dtext->Matched ()) )
{
// stext is the newer version;
if ( wcscmp ( dtext->Get (), stext->Get ()))
{
if ( update )
{
dtext->Set ( stext->Get ());
}
info.modified_strings++;
label_modified = TRUE;
info.changes ++;
}
if ( wcsicmp ( dtext->Wave (), stext->Wave ()))
{
if ( update )
{
dtext->SetWave ( stext->Wave ());
}
info.updated_waves++;
label_modified = TRUE;
info.changes ++;
}
if ( dtext->Retranslate ())
{
if ( update )
{
dtext->IncRevision ();
}
label_modified = TRUE;
}
dtext->SetRetranslate ( FALSE );
}
dtext = destination->NextText ( sh );
}
// any remaining umatched text in the source are new strings
// any remaining umatched text in the destination are now obsolete
// delete old strings from destination
dtext = destination->FirstText ( sh );
while ( dtext )
{
BabylonText *next = destination->NextText ( sh );
if ( !dtext->Matched ())
{
if ( update )
{
dtext->Remove ();
destDB->AddObsolete ( dtext );
}
info.deleted_strings++;
label_modified = TRUE;
info.changes ++;
}
dtext = next;
}
// add new strings from source
stext = source->FirstText ( sh );
while ( stext )
{
if ( !stext->Matched ())
{
if ( update )
{
dtext = stext->Clone ();
destination->AddText ( dtext );
}
info.new_strings++;
label_modified = TRUE;
info.changes ++;
}
stext = source->NextText ( sh );
}
// finally update label info
MACRO_UPDATE(Comment, info.updated_comments);
MACRO_UPDATE(Context, info.updated_contexts);
MACRO_UPDATE(Speaker, info.updated_speakers);
MACRO_UPDATE(Listener, info.updated_listeners);
if ( destination->MaxLen () != source->MaxLen ())
{
if ( update )
{
destination->SetMaxLen ( source->MaxLen ());
}
label_modified = TRUE;
info.updated_maxlen++;
info.changes ++;
}
if ( label_modified )
{
if ( update )
{
source->ClearChanges ();
}
else
{
source->Changed ();
}
info.modified_labels ++;
}
return IDOK;
}
int CBabylonDlg::UpdateDB(TransDB *source, TransDB *destination, int update )
{
BabylonLabel *slabel;
BabylonLabel *dlabel;
ListSearch sh;
int count = 0;
int result = IDOK;
UPDATEINFO info;
int changes = FALSE;
int diffs = 0;
int skip_all = FALSE;
memset ( &info, 0, sizeof ( info ));
if ( update )
{
sprintf ( buffer, "Updating \"%s\" from \"%s\"...", destination->Name(), source->Name());
Log("");
Status ( buffer );
}
else
{
Status ("Checking for changes...", FALSE );
}
source->ClearProcessed ();
destination->ClearProcessed ();
if ( update )
{
InitProgress ( source->NumLabels() );
}
slabel = source->FirstLabel ( sh );
while ( slabel )
{
if ( (dlabel = destination->FindLabel ( slabel->Name ())))
{
dlabel->Processed ();
result = UpdateLabel ( slabel, dlabel, info, update, skip_all );
if ( result == IDCANCEL )
{
skip_all = TRUE;
}
if ( result == IDOK )
{
if ( update )
{
slabel->ClearChanges ();
}
}
else
{
info.skipped_labels ++;
info.changes ++;
if ( !update )
{
slabel->Changed();
}
}
}
else
{
BabylonLabel *clone;
if ( update )
{
clone = slabel->Clone ();
destination->AddLabel ( clone );
clone->Processed ();
slabel->ClearChanges ();
}
else
{
slabel->Changed ();
}
info.new_strings += slabel->NumStrings ();
info.changes += slabel->NumStrings ();
info.new_labels++;
info.changes++;
}
count++;
if ( update )
{
SetProgress ( count );
}
slabel->Processed ();
slabel = source->NextLabel ( sh );
}
// go through all unprocessed labels in the destination database and remove them.
dlabel = destination->FirstLabel ( sh );
while ( dlabel )
{
BabylonLabel *next_label = destination->NextLabel ( sh );
if ( !dlabel->IsProcessed ())
{
// this label was not matched so is obsolete
ListSearch sh_text;
BabylonText *dtext = dlabel->FirstText ( sh_text);
while ( dtext )
{
BabylonText *next = dlabel->NextText ( sh_text );
if ( update )
{
dtext->Remove ();
destination->AddObsolete ( dtext );
}
info.deleted_strings++;
info.changes ++;
dtext = next;
}
if ( update )
{
dlabel->Remove ();
delete dlabel;
}
info.deleted_labels++;
}
dlabel = next_label;
}
if ( update )
{
if ( info.new_labels )
{
sprintf ( buffer, "Added %d new label%c", info.new_labels, info.new_labels==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.deleted_labels )
{
sprintf ( buffer, "Deleted %d label%c", info.deleted_labels, info.deleted_labels==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.modified_labels )
{
sprintf ( buffer, "Modified %d label%c", info.modified_labels, info.modified_labels==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.new_strings )
{
sprintf ( buffer, "Added %d new string%c", info.new_strings, info.new_strings==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.deleted_strings )
{
sprintf ( buffer, "Deleted %d string%c", info.deleted_strings, info.deleted_strings==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.modified_strings )
{
sprintf ( buffer, "Modified %d string%c", info.modified_strings, info.modified_strings==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.skipped_labels )
{
sprintf ( buffer, "Skipped %d label%c", info.skipped_labels, info.skipped_labels==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.updated_comments )
{
sprintf ( buffer, "Updated %d comment%c", info.updated_comments, info.updated_comments==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.updated_contexts )
{
sprintf ( buffer, "Updated %d context%c", info.updated_contexts, info.updated_contexts==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.updated_speakers )
{
sprintf ( buffer, "Updated %d speaker%c", info.updated_speakers, info.updated_speakers==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.updated_listeners )
{
sprintf ( buffer, "Updated %d listener%c", info.updated_listeners, info.updated_listeners==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.updated_maxlen )
{
sprintf ( buffer, "Updated %d max length%c", info.updated_maxlen, info.updated_maxlen==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( info.updated_waves )
{
sprintf ( buffer, "Updated %d speech file%c", info.updated_waves, info.updated_waves==1?' ':'s' );
Log ( buffer );
changes = TRUE;
}
if ( !changes )
{
if ( !slabel && !info.skipped_labels)
{
Log ( "No differences found" );
}
else
{
Log ( "No changes made" );
}
}
if ( result == IDCANCEL )
{
Log ("Update aborted by user!" );
InitProgress ( 100 );
}
else
{
if ( !info.skipped_labels )
{
source->ClearChanges ();
}
}
} // update
Ready ();
return info.changes;
}
void CBabylonDlg::OnSave()
{
if ( CanOperate ())
{
SaveMainDB ( );
}
}
int CBabylonDlg::SaveMainDB( )
{
TransDB *db = MainDB;
const char *filename = MainXLSFilename;
int attribs;
if ( !db )
{
return TRUE;
}
if ( !db->IsChanged ())
{
return TRUE;
}
attribs = FileAttribs ( filename );
if ( attribs & FA_READONLY )
{
char buffer[100];
sprintf ( buffer, "Cannot save changes!\n\nFile \"%s\" is read only", filename );
AfxMessageBox ( buffer );
sprintf ( buffer, "Cannot save to \"%s\". File is read only", filename );
Log ( buffer );
Status ("Save failed", FALSE );
return FALSE;
}
Log("");
Status ( "Saving main database..." );
if ( attribs != FA_NOFILE )
{
MakeBackupFile ( filename );
}
if ( !WriteMainDB ( db, filename, this ) )
{
RestoreBackupFile ( filename );
Log ("FAILED", SAME_LINE );
Status ("Save failed", FALSE );
return FALSE;
}
else
{
Log ("OK", SAME_LINE );
}
Ready();
return TRUE;
}
void CBabylonDlg::OnWarnings()
{
// TODO: Add your control notification handler code here
if ( BabylonstrDB )
{
BabylonstrDB->Warnings ( this );
}
}
void CBabylonDlg::OnErrors()
{
// TODO: Add your control notification handler code here
if ( BabylonstrDB )
{
BabylonstrDB->Errors ( this );
}
}
int CBabylonDlg::MatchText ( BabylonText *text, BabylonLabel *label, BabylonText **match )
{
CMatchDlg dlg;
int result;
*match = NULL;
sprintf ( buffer, "Text: %s\n\nLabel:%s\n", text->GetSB (), label->NameSB () );
// TODO: Add your control notification handler code here
MatchOriginalText = text;
MatchLabel = label;
result = dlg.DoModal ();
if ( result != IDCANCEL )
{
*match = MatchingBabylonText;
}
return result;
}
int CBabylonDlg::RetranslateText ( BabylonText *newtext, BabylonText *oldtext )
{
RetranslateDlg dlg;
int result;
// TODO: Add your control notification handler code here
dlg.newtext = newtext;
dlg.oldtext = oldtext;
result = dlg.DoModal ( );
return result;
}
void CBabylonDlg::OnChanges()
{
// TODO: Add your control notification handler code here
VIEWDBSII dlg;
ViewChanges = TRUE;
dlg.DoModal ();
}
void CBabylonDlg::OnImport()
{
if ( CanOperate ())
{
CFileDialog fd ( TRUE , NULL, "*.xls", OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR );
if ( fd.DoModal () == IDOK )
{
if (ImportTranslations ( MainDB, (LPCSTR ) fd.GetPathName (), this ) == -1 )
{
// ProcessWaves ( BabylonstrDB, fd.GetPathName (), this );
}
}
}
}
void CBabylonDlg::OnGenerate()
{
if ( CanOperate ())
{
CGenerateDlg dlg;
if ( dlg.DoModal () == IDOK )
{
GenerateGameFiles ( MainDB, dlg.FilePrefix(), dlg.Options(), dlg.Langauges(), this );
}
}
}
int CBabylonDlg::ValidateStrFile( const char *filename)
{
STARTUPINFO StartupInfo = { 0 };
PROCESS_INFORMATION ProcessInfo;
char *results = "strcheck.rst";
int errors = 0;
FILE *file = NULL;
StartupInfo.cb = sizeof(STARTUPINFO);
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_SHOWMINNOACTIVE;
Log ("");
sprintf ( buffer, "Verifying \"%s\"...", filename );
Status ( buffer );
if ( FileExists ( results ))
{
DeleteFile ( results );
}
sprintf ( buffer, "strcheck %s %s", filename, results );
if (!CreateProcess(
NULL,
buffer,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&StartupInfo,
&ProcessInfo))
{
goto error;
}
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
//this->SetForegroundWindow ();
//this->RedrawWindow ();
if ( !(file = fopen ( results, "rt" )))
{
goto error;
}
while ( fgets ( buffer, sizeof(buffer), file ) )
{
strlwr ( buffer );
if ( strstr ( buffer, "error") || strstr ( buffer, "warning" ))
{
errors++;
}
}
if ( errors )
{
sprintf ( buffer, "%d ERROR%s", errors, errors == 1 ? "" : "S" );
Log (buffer, SAME_LINE );
fseek ( file, 0, SEEK_SET );
while ( fgets ( buffer, sizeof(buffer), file ) )
{
sprintf ( buffer2, " strcheck> %s", buffer );
strlwr ( buffer );
if ( strstr ( buffer2, "error") || strstr ( buffer, "warning" ) )
{
int len = strlen ( buffer2 );
if ( buffer2[len-1] == '\n' )
{
buffer2[len-1] = 0;
}
Log ( buffer2 );
}
}
}
else
{
Log ("OK", SAME_LINE );
}
done:
if ( FileExists ( results ))
{
DeleteFile ( results );
}
if (file )
{
fclose (file );
}
return errors;
error:
Log ( "UNABLE TO VERIFY", SAME_LINE );
errors = -1;
goto done;
}
void CBabylonDlg::OnVerifyDialog()
{
if ( MainDB && CanOperate () )
{
VerifyDialog ( MainDB, CurrentLanguage );
}
}
void CBabylonDlg::VerifyDialog( TransDB *db, LangID langid )
{
BabylonLabel *label;
ListSearch sh_label;
int count = 0;
DLGREPORT _info;
DLGREPORT *info = &_info;
Log ("");
sprintf ( buffer, "Verifying %s dialog...", GetLangName ( langid ) );
Status ( buffer );
InitProgress ( db->NumLabels () );
cb_count = 0;
mainDlg = this;
db->VerifyDialog ( langid, cb_progress );
db->ReportDialog ( info, langid);
if ( info->unresolved )
{
Status ( "Verification", FALSE);
InitProgress ( info->unresolved );
label = db->FirstLabel ( sh_label );
while ( label )
{
BabylonText *text;
ListSearch sh_text;
text = label->FirstText ( sh_text );
while ( text )
{
if ( text->IsDialog ())
{
if ( text->DialogIsPresent ( DialogPath, langid ))
{
if ( !text->DialogIsValid ( DialogPath, langid, FALSE ) )
{
VerifyDlg dlg(text, langid, DialogPath);
int result;
result = dlg.DoModal ();
if ( result == IDCANCEL )
{
goto done;
}
if ( result == IDOK )
{
text->ValidateDialog ( DialogPath, langid );
}
count++;
SetProgress ( count );
}
}
}
text = label->NextText ( sh_text );
}
label = db->NextLabel ( sh_label );
}
}
done:
Ready ();
Status ( "Collecting stats...", FALSE );
count = db->ReportDialog ( info, langid );
if ( count < 100 )
{
InitProgress ( count );
cb_count = 0;
found_error = FALSE;
mainDlg = this;
db->ReportDialog ( info, langid, print_to_log_and_update_progress );
}
if ( info->numdialog )
{
if ( info->errors || info->missing || info->unresolved )
{
if ( !found_error )
{
Log ( "FAILED", SAME_LINE );
}
if ( info->errors )
{
sprintf ( buffer, "Errors : %d", info->errors );
Log ( buffer );
}
if ( info->missing )
{
sprintf ( buffer, "Missing dialog : %d", info->missing );
Log ( buffer );
}
if ( info->unresolved )
{
sprintf ( buffer, "Unverified dialog: %d", info->unresolved );
Log ( buffer );
}
if ( info->resolved )
{
sprintf ( buffer, "Verified dialog : %d", info->resolved );
Log ( buffer );
}
}
else
{
Log ( "OK", SAME_LINE );
if ( info->resolved )
{
sprintf ( buffer, "Verified dialog : %d", info->resolved );
Log ( buffer );
}
}
sprintf ( buffer, "Total dialog : %d", info->numdialog );
Log ( buffer );
}
else
{
Log ( "NO DIALOG FOUND", SAME_LINE );
}
Ready();
}
void CBabylonDlg::VerifyTranslations( TransDB *db, LangID langid )
{
int count = 0;
TRNREPORT _info;
TRNREPORT *info = &_info;
Log ("");
sprintf ( buffer, "Verifying %s text...", GetLangName ( langid ) );
Status ( buffer );
count = db->ReportTranslations ( info, langid );
if ( count < 100 )
{
InitProgress ( count);
cb_count = 0;
found_error = FALSE;
mainDlg = this;
db->ReportTranslations ( info, langid, print_to_log_and_update_progress );
}
if ( info->numstrings )
{
if ( info->too_big || info->missing || info->retranslate || info->bad_format )
{
if ( info->missing )
{
sprintf ( buffer, "Missing translations: %d", info->missing );
Log ( buffer );
}
if ( info->too_big )
{
sprintf ( buffer, "Oversized strings : %d", info->too_big );
Log ( buffer );
}
if ( info->retranslate )
{
sprintf ( buffer, "Retranslations : %d", info->retranslate);
Log ( buffer );
}
if ( info->bad_format )
{
sprintf ( buffer, "Badly formated translations: %d", info->bad_format);
Log ( buffer );
}
if ( langid == LANGID_US )
{
sprintf ( buffer, "Recommemd editing \"%s\" to fix problems and reload", BabylonstrFilename );
}
else
{
sprintf ( buffer, "Recommemd exporting translations for update and re-import" );
}
Log ( buffer );
}
else
{
Log ( "OK", SAME_LINE );
}
}
else
{
Log ( "NO TEXT", SAME_LINE );
}
Ready();
}
void CBabylonDlg::OnTranslations()
{
if ( MainDB && CanOperate () )
{
VerifyTranslations ( MainDB, CurrentLanguage );
}
}
void CBabylonDlg::OnSelchangeCombolang()
{
LANGINFO *info = NULL;
int index;
index = combo->GetCurSel ();
if ( index >= 0 && index < max_index )
{
info = (LANGINFO *) combo->GetItemDataPtr ( index );
}
if ( info )
{
CurrentLanguage = info->langid;
}
else
{
CurrentLanguage = LANGID_UNKNOWN;
}
}
void CBabylonDlg::OnReports()
{
// TODO: Add your control notification handler code here
if ( CanOperate ())
{
CReport dlg;
if ( dlg.DoModal () == IDOK )
{
GenerateReport ( MainDB, dlg.Filename(), dlg.Options(), dlg.Langauges(), this );
}
}
}
void CBabylonDlg::OnDblclkCombolang()
{
// TODO: Add your control notification handler code here
}
void CBabylonDlg::OnReset()
{
// TODO: Add your control notification handler code here
if ( CurrentLanguage != LANGID_UNKNOWN )
{
sprintf ( buffer, "Are you sure you want to invalidate all %s dialog?", GetLangName ( CurrentLanguage ));
if ( AfxMessageBox ( buffer, MB_YESNO) == IDYES )
{
MainDB->InvalidateDialog ( CurrentLanguage );
}
}
}
void CBabylonDlg::OnSent()
{
// TODO: Add your control notification handler code here
if ( CanOperate ())
{
CFileDialog fd ( TRUE , NULL, "*.xls", OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR );
if ( fd.DoModal () == IDOK )
{
UpdateSentTranslations ( MainDB, (LPCSTR ) fd.GetPathName (), this );
}
}
}
void CAboutDlg::OnButton1()
{
// TODO: Add your control notification handler code here
CreateTranslationTable ( );
}