expimp.cpp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. //
  19. // expimp.cpp
  20. //
  21. #include "stdAfx.h"
  22. #include "transDB.h"
  23. #include "XLStuff.h"
  24. #include "Noxstringdlg.h"
  25. #include "VerifyTextDlg.h"
  26. #include "Noxstring.h"
  27. #include "expimp.h"
  28. #include "direct.h"
  29. #include "fileops.h"
  30. #include "olestring.h"
  31. static char buffer[100*1024];
  32. static char buffer2[100*1024];
  33. static OLECHAR olebuf[100*1024];
  34. static OLECHAR olebuf2[100*1024];
  35. static OLECHAR oletrans[100*1024];
  36. static CNoxstringDlg *progress_dlg;
  37. static int progress_count;
  38. static void progress_cb ( void )
  39. {
  40. progress_count ++;
  41. if ( progress_dlg )
  42. {
  43. progress_dlg->SetProgress ( progress_count );
  44. }
  45. }
  46. static FILE *cb_file;
  47. static void print_to_file ( const char *text )
  48. {
  49. fprintf ( cb_file, "\t\t\tString %s\n", text );
  50. }
  51. static void reverseWord ( OLECHAR *fp, OLECHAR *lp )
  52. {
  53. int first = TRUE;
  54. OLECHAR f, l;
  55. while ( TRUE )
  56. {
  57. if ( fp >= lp )
  58. {
  59. return;
  60. }
  61. f = *fp;
  62. l = *lp;
  63. if ( first )
  64. {
  65. if ( f >= 'A' && f <= 'Z' )
  66. {
  67. if ( l >= 'a' && l <= 'z' )
  68. {
  69. f = (f - 'A') + 'a';
  70. l = (l - 'a') + 'A';
  71. }
  72. }
  73. first = FALSE;
  74. }
  75. *lp-- = f;
  76. *fp++ = l;
  77. }
  78. }
  79. static void translateCopy( OLECHAR *outbuf, OLECHAR *inbuf )
  80. {
  81. int slash = FALSE;
  82. {
  83. static OLECHAR buffer[100*1024];
  84. OLECHAR *firstLetter = NULL, *lastLetter;
  85. OLECHAR *b = buffer;
  86. int formatWord = FALSE;
  87. OLECHAR ch;
  88. while ( (ch = *inbuf++))
  89. {
  90. if ( ! (( ch >= 'a' && ch <= 'z') || ( ch >= 'A' && ch <= 'Z' )))
  91. {
  92. if ( firstLetter )
  93. {
  94. if ( !formatWord )
  95. {
  96. lastLetter = b-1;
  97. reverseWord ( firstLetter, lastLetter );
  98. }
  99. firstLetter = NULL;
  100. formatWord = FALSE;
  101. }
  102. *b++ = ch;
  103. if ( ch == '\\' )
  104. {
  105. *b++ = *inbuf++;
  106. }
  107. if ( ch == '%' )
  108. {
  109. while ( (ch = *inbuf++) && !IsFormatTypeChar ( ch ) && ch != '%')
  110. {
  111. *b++ = ch;
  112. }
  113. *b++ = ch;
  114. }
  115. }
  116. else
  117. {
  118. if ( !firstLetter )
  119. {
  120. firstLetter = b;
  121. }
  122. *b++ = ch;
  123. }
  124. }
  125. if ( firstLetter )
  126. {
  127. lastLetter = b-1;
  128. reverseWord ( firstLetter, lastLetter );
  129. }
  130. *b++ = 0;
  131. inbuf = buffer;
  132. }
  133. while( *inbuf != '\0' )
  134. {
  135. *outbuf++ = *inbuf++;
  136. }
  137. *outbuf= 0;
  138. }
  139. static void writeLabel ( NoxLabel *label, int row )
  140. {
  141. PutCell ( row, CELL_LABEL, label->Name (), 0);
  142. wcscpy ( olebuf, label->Comment());
  143. EncodeFormat ( olebuf );
  144. PutCell ( row, CELL_COMMENT, olebuf, 0);
  145. wcscpy ( olebuf, label->Context());
  146. EncodeFormat ( olebuf );
  147. PutCell ( row, CELL_CONTEXT, olebuf, 0);
  148. wcscpy ( olebuf, label->Speaker());
  149. EncodeFormat ( olebuf );
  150. PutCell ( row, CELL_SPEAKER, olebuf, 0);
  151. wcscpy ( olebuf, label->Listener());
  152. EncodeFormat ( olebuf );
  153. PutCell ( row, CELL_LISTENER, olebuf , 0);
  154. }
  155. static void writeText ( NoxText *text, int row )
  156. {
  157. NoxLabel *label = text->Label ();
  158. int maxlen = label->MaxLen ();
  159. OLECHAR buffer[100];
  160. if ( !maxlen )
  161. {
  162. maxlen = 10000;
  163. }
  164. wcscpy ( olebuf, text->Get());
  165. EncodeFormat ( olebuf );
  166. PutCell ( row, CELL_ENGLISH, olebuf , 0);
  167. PutCell ( row, CELL_MAXLEN, NULL , maxlen );
  168. swprintf ( buffer, L"=LEN(%c%d)",'A' + CELL_LOCALIZED -1, row );
  169. PutCell ( row, CELL_STRLEN, buffer , 0);
  170. swprintf ( buffer, L"=IF(%c%d>%c%d,\"Too long!\",\" \")", 'A' + CELL_STRLEN -1, row, 'A' + CELL_MAXLEN -1, row );
  171. PutCell ( row, CELL_LENCHECK ,buffer , 0);
  172. PutCell ( row, CELL_REVISION , 0, text->Revision ());
  173. PutCell ( row, CELL_STRINGID , 0, text->ID ());
  174. writeLabel ( label, row );
  175. }
  176. static int export_trans ( TransDB *db, LangID langid, TROPTIONS *options, void (*cb) (void ), int write )
  177. {
  178. NoxLabel *label;
  179. NoxText *text;
  180. Translation *trans;
  181. ListSearch sh_label, sh_text;
  182. int count = 0;
  183. int limit = FALSE;
  184. int all = TRUE;
  185. int row;
  186. LANGINFO *linfo;
  187. linfo = GetLangInfo ( langid );
  188. if ( options->filter == TR_SAMPLE )
  189. {
  190. limit = TRUE;
  191. }
  192. else if ( options->filter == TR_CHANGES )
  193. {
  194. all = FALSE;
  195. }
  196. if ( write )
  197. {
  198. OLECHAR buffer[100];
  199. swprintf ( buffer, L"%S", GetLangName ( langid ));
  200. PutCell ( ROW_LANGUAGE, COLUMN_LANGUAGE,buffer,0);
  201. swprintf ( buffer, L"%S Translation", GetLangName ( langid ));
  202. PutCell ( 2, CELL_LOCALIZED,buffer,0);
  203. }
  204. row = 3;
  205. label = db->FirstLabel ( sh_label );
  206. while ( label )
  207. {
  208. int label_written = FALSE;
  209. text = label->FirstText ( sh_text );
  210. while ( text )
  211. {
  212. int export;
  213. int bad_format = FALSE;
  214. int too_long = FALSE;
  215. trans = text->GetTranslation ( langid );
  216. if ( options->filter == TR_UNSENT )
  217. {
  218. export = !text->IsSent ();
  219. }
  220. else if ( options->filter == TR_NONDIALOG )
  221. {
  222. export = !text->IsDialog ();
  223. }
  224. else if ( options->filter == TR_UNVERIFIED )
  225. {
  226. export = text->IsDialog() && text->DialogIsPresent( DialogPath, langid) && !text->DialogIsValid( DialogPath, langid);
  227. }
  228. else if ( options->filter == TR_MISSING_DIALOG )
  229. {
  230. export = text->IsDialog() && !text->DialogIsPresent( DialogPath, langid);
  231. }
  232. else if ( options->filter == TR_DIALOG )
  233. {
  234. export = text->IsDialog ();
  235. }
  236. else
  237. {
  238. if ( ! (export = all) )
  239. {
  240. if ( !trans )
  241. {
  242. export = TRUE;
  243. }
  244. else
  245. {
  246. if ( text->Revision () > trans->Revision ())
  247. {
  248. export = TRUE;
  249. }
  250. else if ( trans->TooLong ( label->MaxLen ()) )
  251. {
  252. export = TRUE;
  253. too_long = TRUE;
  254. }
  255. else if ( !trans->ValidateFormat ( text ) )
  256. {
  257. export = TRUE;
  258. bad_format = TRUE;
  259. }
  260. }
  261. }
  262. }
  263. if ( export && text->Len () )
  264. {
  265. count++;
  266. if ( cb )
  267. {
  268. cb ();
  269. }
  270. if ( write )
  271. {
  272. static OLECHAR buffer[100*1024];
  273. if ( !label_written )
  274. {
  275. // write out the lable
  276. //PutSeparator ( row++ );
  277. //writeLabel ( label, row );
  278. label_written = TRUE;
  279. }
  280. // write out text
  281. writeText ( text, row );
  282. if ( text->IsDialog ())
  283. {
  284. swprintf ( buffer, L"%s%S.wav", text->Wave (), linfo->character );
  285. wcsupr ( buffer );
  286. PutCell ( row, CELL_WAVEFILE , buffer, 0);
  287. }
  288. {
  289. Translation *trans = text->GetTranslation ( langid );
  290. if ( langid == LANGID_JABBER || (trans && ( options->include_translations || too_long || bad_format )))
  291. {
  292. if ( langid == LANGID_JABBER )
  293. {
  294. translateCopy ( olebuf, text->Get() );
  295. }
  296. else
  297. {
  298. wcscpy ( olebuf, trans->Get());
  299. }
  300. EncodeFormat ( olebuf );
  301. PutCell ( row, CELL_LOCALIZED, olebuf, 0);
  302. if ( bad_format || too_long)
  303. {
  304. wcscpy ( olebuf, L"ERROR: " );
  305. if ( too_long )
  306. {
  307. wcscat ( olebuf, L"too long" );
  308. if ( bad_format )
  309. {
  310. wcscat ( olebuf, L"and " );
  311. }
  312. }
  313. if ( bad_format )
  314. {
  315. wcscat ( olebuf, L"bad format" );
  316. }
  317. PutCell ( row, CELL_COMMENT, olebuf , 0);
  318. }
  319. }
  320. }
  321. row++;
  322. }
  323. }
  324. text = label->NextText ( sh_text );
  325. }
  326. if ( limit && count > 50 )
  327. {
  328. break;
  329. }
  330. label = db->NextLabel ( sh_label );
  331. }
  332. if ( write )
  333. {
  334. PutCell ( row, CELL_STRINGID, NULL, -1 );
  335. PutCell ( ROW_COUNT, COLUMN_COUNT, NULL, count );
  336. }
  337. return count;
  338. }
  339. int ExportTranslations ( TransDB *db, const char *filename, LangID langid, TROPTIONS *options, CNoxstringDlg *dlg )
  340. {
  341. int exports ;
  342. exports = export_trans ( db, langid, options, NULL, FALSE );
  343. if ( !exports )
  344. {
  345. if ( dlg )
  346. {
  347. AfxMessageBox ( "Nothing to export." );
  348. dlg->Ready ();
  349. }
  350. return 0;
  351. }
  352. if ( (progress_dlg = dlg) )
  353. {
  354. char *format;
  355. dlg->InitProgress ( exports );
  356. dlg->Log ("");
  357. switch (options->filter )
  358. {
  359. case TR_ALL:
  360. format = "Exporting all strings";
  361. break;
  362. case TR_CHANGES:
  363. format = "Exporting all strings that require %s translation";
  364. break;
  365. case TR_SAMPLE:
  366. format = "Exporting a sample %s translation file";
  367. break;
  368. case TR_DIALOG:
  369. format = "Exporting dialog only %s translation file";
  370. break;
  371. case TR_NONDIALOG:
  372. format = "Exporting non-dialog %s translation file";
  373. break;
  374. case TR_UNVERIFIED:
  375. format = "Exporting all unverified %s dialog";
  376. break;
  377. case TR_MISSING_DIALOG:
  378. format = "Exporting all missing %s dialog";
  379. break;
  380. default:
  381. format = "Undefined switch";
  382. break;
  383. }
  384. strcpy ( buffer2, format );
  385. if ( options->include_comments && options->include_translations )
  386. {
  387. strcat ( buffer2, " with current %s translations and translator comments" );
  388. }
  389. else if ( options->include_comments )
  390. {
  391. strcat ( buffer2, " with %s translator comments" );
  392. }
  393. else if ( options->include_translations )
  394. {
  395. strcat ( buffer2, " with current %s translations" );
  396. }
  397. strcat ( buffer2, "..." );
  398. sprintf ( buffer, buffer2, GetLangName ( langid ), GetLangName ( langid ) );
  399. dlg->Status ( buffer );
  400. }
  401. _getcwd ( buffer, sizeof ( buffer ) -1 );
  402. strcat ( buffer, "\\babylon.xlt" );
  403. if ( !FileExists ( buffer ) )
  404. {
  405. if ( dlg )
  406. {
  407. dlg->Log ("FAILED", SAME_LINE );
  408. sprintf ( buffer2, "Template file \"%s\" is missing. Cannot export.", buffer );
  409. AfxMessageBox ( buffer2 );
  410. dlg->Log ( buffer2 );
  411. dlg->Ready();
  412. }
  413. return -1;
  414. }
  415. progress_count = 0;
  416. exports = -1;
  417. if ( NewWorkBook ( buffer ) )
  418. {
  419. if ( (exports = export_trans ( db, langid, options, progress_cb, TRUE )) != -1 )
  420. {
  421. if ( SaveWorkBook ( filename, TRUE ) )
  422. {
  423. if ( dlg )
  424. {
  425. dlg->Log ("DONE", SAME_LINE );
  426. }
  427. }
  428. else
  429. {
  430. if ( dlg )
  431. {
  432. dlg->Log ("FAILED", SAME_LINE );
  433. sprintf ( buffer2, "Failed to save export!");
  434. AfxMessageBox ( buffer2 );
  435. dlg->Log ( buffer2 );
  436. }
  437. exports = -1;
  438. }
  439. }
  440. CloseWorkBook ( );
  441. }
  442. else
  443. {
  444. if ( dlg )
  445. {
  446. dlg->Log ("FAILED", SAME_LINE );
  447. sprintf ( buffer2, "Failed to create new work book. File \"%s\" may be corrupt", buffer );
  448. AfxMessageBox ( buffer2 );
  449. dlg->Log ( buffer2 );
  450. }
  451. }
  452. if ( dlg )
  453. {
  454. dlg->Ready();
  455. }
  456. return exports;
  457. }
  458. static int import_trans ( TransDB *db, LangID langid, void (*cb) ( void ), CNoxstringDlg *dlg )
  459. {
  460. int row = 3;
  461. int id;
  462. int count = 0;
  463. int new_count = 0;
  464. int changes_count = 0;
  465. int missing_count = 0;
  466. int mismatch_count = 0;
  467. int stale_count = 0;
  468. int first_mismatch = TRUE;
  469. int bad_id = FALSE;
  470. int error_count = 0;
  471. int revision;
  472. while ( (id = GetInt ( row, CELL_STRINGID )) != -1)
  473. {
  474. if ( id == 0 )
  475. {
  476. goto skip;
  477. }
  478. NoxText *text;
  479. if ( (text = db->FindText ( id )) == NULL )
  480. {
  481. // string is no longer in database
  482. stale_count++;
  483. goto next;
  484. }
  485. revision = GetInt ( row, CELL_REVISION );
  486. if ( text->Revision() > revision )
  487. {
  488. // old translation
  489. stale_count++;
  490. goto next;
  491. }
  492. if ( text->Revision() < revision )
  493. {
  494. if ( dlg )
  495. {
  496. sprintf ( buffer, "ERROR: expecting revision %d for string ID %d but found revision %d. Possible bad ID!", text->Revision (), id, revision );
  497. dlg->Log ( buffer );
  498. }
  499. error_count++;
  500. goto next;
  501. }
  502. // first see if there is any translation there
  503. GetString ( row, CELL_LOCALIZED, oletrans );
  504. DecodeFormat ( oletrans );
  505. if ( !oletrans[0] )
  506. {
  507. missing_count++;
  508. goto next;
  509. }
  510. // verify that the translated engish is the same as the current english
  511. GetString ( row, CELL_ENGLISH, olebuf );
  512. DecodeFormat ( olebuf );
  513. if ( wcscmp ( text->Get(), olebuf ) )
  514. {
  515. // they are two possible reasons for the text to mismatch
  516. // 1. text was modified but not re-translated
  517. // 2. the IDs are wrong
  518. //
  519. // to check for the first case we search for the label in the xl file
  520. // and make sure it is the same. If not then we have problems
  521. int nrow = row;
  522. olebuf2[0] = 0;
  523. while ( nrow > 0 )
  524. {
  525. GetString ( nrow, CELL_LABEL, olebuf2 );
  526. if ( olebuf2[0] )
  527. {
  528. break;
  529. }
  530. nrow--;
  531. }
  532. if ( !olebuf2[0] || wcscmp ( text->Label ()->Name(), olebuf2))
  533. {
  534. sprintf ( buffer, "%S", olebuf );
  535. CVerifyTextDlg dlg(buffer, text->GetSB());
  536. // didnt find label or label doesn't match
  537. // It is possible that the xl was resorted so ask user to do a visual confirmation
  538. bad_id = dlg.DoModal ()==IDNO;
  539. }
  540. else if ( text->Label()->FindText( olebuf ))
  541. {
  542. // we did find the label but text other than the current ID sourced text matches with the import text
  543. // this means the ID is definitely wrong
  544. bad_id = TRUE;
  545. }
  546. else
  547. {
  548. bad_id = FALSE;
  549. }
  550. if ( bad_id )
  551. {
  552. goto done;
  553. }
  554. }
  555. // ok import the translation
  556. Translation *trans;
  557. if ( ! (trans = text->GetTranslation ( langid )))
  558. {
  559. new_count++;
  560. trans = new Translation ();
  561. trans->SetLangID ( langid );
  562. text->AddTranslation ( trans );
  563. }
  564. if ( trans->Revision () == revision && !wcscmp ( trans->Get (), oletrans ))
  565. {
  566. // already up to date
  567. goto next;
  568. }
  569. trans->Set ( oletrans );
  570. trans->WaveInfo.SetValid ( FALSE );
  571. trans->SetRevision ( revision );
  572. changes_count++;
  573. next:
  574. count++;
  575. if ( cb )
  576. {
  577. cb ();
  578. }
  579. skip:
  580. row++;
  581. }
  582. done:
  583. if ( dlg )
  584. {
  585. sprintf ( buffer, "Total found : %d", count );
  586. dlg->Log ( buffer );
  587. {
  588. sprintf ( buffer, "New : %d", new_count);
  589. dlg->Log ( buffer );
  590. }
  591. {
  592. sprintf ( buffer, "Updates : %d", (changes_count - new_count));
  593. dlg->Log ( buffer );
  594. }
  595. if ( missing_count )
  596. {
  597. sprintf ( buffer, "Missing : %d", missing_count );
  598. dlg->Log ( buffer );
  599. }
  600. if ( stale_count )
  601. {
  602. sprintf ( buffer, "Unmatched : %d", stale_count);
  603. dlg->Log ( buffer );
  604. }
  605. }
  606. if ( bad_id )
  607. {
  608. if ( dlg )
  609. {
  610. sprintf ( buffer, "Aborting import: BAD IDs");
  611. dlg->Log ( buffer );
  612. }
  613. AfxMessageBox ("The imported translation file has bad string IDs! Fix the string IDs and re-import" );
  614. }
  615. return count;
  616. }
  617. static int update_sent_trans ( TransDB *db, LangID langid, void (*cb) ( void ), CNoxstringDlg *dlg )
  618. {
  619. int row = 3;
  620. int id;
  621. int count = 0;
  622. int new_count = 0;
  623. int matched = 0;
  624. int unmatched = 0;
  625. int changed = 0;
  626. int first_mismatch = TRUE;
  627. int bad_id = FALSE;
  628. int error_count = 0;
  629. int revision;
  630. while ( (id = GetInt ( row, CELL_STRINGID )) != -1)
  631. {
  632. if ( id == 0 )
  633. {
  634. goto skip;
  635. }
  636. NoxText *text;
  637. if ( (text = db->FindText ( id )) == NULL )
  638. {
  639. // string is no longer in database
  640. unmatched++;
  641. goto next;
  642. }
  643. revision = GetInt ( row, CELL_REVISION );
  644. if ( text->Revision() > revision )
  645. {
  646. // old translation
  647. changed++;
  648. goto next;
  649. }
  650. if ( text->Revision() < revision )
  651. {
  652. if ( dlg )
  653. {
  654. sprintf ( buffer, "ERROR: expecting revision %d for string ID %d but found revision %d. Possible bad ID!", text->Revision (), id, revision );
  655. dlg->Log ( buffer );
  656. }
  657. error_count++;
  658. goto next;
  659. }
  660. // verify that the translated engish is the same as the current english
  661. GetString ( row, CELL_ENGLISH, olebuf );
  662. DecodeFormat ( olebuf );
  663. if ( wcscmp ( text->Get(), olebuf ) )
  664. {
  665. // they are two possible reasons for the text to mismatch
  666. // 1. text was modified but not re-translated
  667. // 2. the IDs are wrong
  668. //
  669. // to check for the first case we search for the label in the xl file
  670. // and make sure it is the same. If not then we have problems
  671. int nrow = row;
  672. olebuf2[0] = 0;
  673. while ( nrow > 0 )
  674. {
  675. GetString ( nrow, CELL_LABEL, olebuf2 );
  676. if ( olebuf2[0] )
  677. {
  678. break;
  679. }
  680. nrow--;
  681. }
  682. if ( !olebuf2[0] || wcscmp ( text->Label ()->Name(), olebuf2))
  683. {
  684. sprintf ( buffer, "%S", olebuf );
  685. CVerifyTextDlg dlg(buffer, text->GetSB());
  686. // didnt find label or label doesn't match
  687. // It is possible that the xl was resorted so ask user to do a visual confirmation
  688. bad_id = dlg.DoModal ()==IDNO;
  689. }
  690. else if ( text->Label()->FindText( olebuf ))
  691. {
  692. // we did find the label but text other than the current ID sourced text matches with the import text
  693. // this means the ID is definitely wrong
  694. bad_id = TRUE;
  695. }
  696. else
  697. {
  698. bad_id = FALSE;
  699. }
  700. if ( bad_id )
  701. {
  702. goto done;
  703. }
  704. }
  705. else
  706. {
  707. // text is still the same
  708. text->Sent ( TRUE );
  709. matched++;
  710. }
  711. next:
  712. count++;
  713. if ( cb )
  714. {
  715. cb ();
  716. }
  717. skip:
  718. row++;
  719. }
  720. done:
  721. if ( dlg )
  722. {
  723. sprintf ( buffer, "Total found : %d", count );
  724. dlg->Log ( buffer );
  725. {
  726. sprintf ( buffer, "Matched : %d", matched);
  727. dlg->Log ( buffer );
  728. }
  729. {
  730. sprintf ( buffer, "Unmatched : %d", unmatched);
  731. dlg->Log ( buffer );
  732. }
  733. if ( changed )
  734. {
  735. sprintf ( buffer, "changed : %d", changed);
  736. dlg->Log ( buffer );
  737. }
  738. }
  739. if ( bad_id )
  740. {
  741. if ( dlg )
  742. {
  743. sprintf ( buffer, "Aborting import: BAD IDs");
  744. dlg->Log ( buffer );
  745. }
  746. AfxMessageBox ("The imported translation file has bad string IDs! Fix the string IDs and re-import" );
  747. }
  748. return count;
  749. }
  750. int ImportTranslations ( TransDB *db, const char *filename, CNoxstringDlg *dlg )
  751. {
  752. int imports = -1;
  753. progress_dlg = dlg;
  754. if ( dlg )
  755. {
  756. dlg->Log ("");
  757. sprintf ( buffer, "Importing \"%s\"...", filename );
  758. dlg->Status ( buffer );
  759. }
  760. if ( OpenWorkBook ( filename ) )
  761. {
  762. int num_strings;
  763. LANGINFO *info;
  764. num_strings = GetInt ( ROW_COUNT, COLUMN_COUNT );
  765. GetString ( ROW_LANGUAGE, COLUMN_LANGUAGE, olebuf );
  766. sprintf ( buffer, "%S", olebuf );
  767. info = GetLangInfo ( buffer );
  768. if ( !info )
  769. {
  770. if ( dlg )
  771. {
  772. AfxMessageBox ( "Import file is of an unknown language or is not a translation file" );
  773. dlg->Log ( "FAILED", SAME_LINE );
  774. dlg->Ready();
  775. }
  776. CloseWorkBook ();
  777. return -1;
  778. }
  779. if ( dlg )
  780. {
  781. dlg->InitProgress ( num_strings );
  782. progress_count = 0;
  783. sprintf ( buffer, "...%s", info->name );
  784. dlg->Log ( buffer, SAME_LINE );
  785. }
  786. imports = import_trans ( db, info->langid, progress_cb, dlg );
  787. CloseWorkBook ( );
  788. }
  789. else
  790. {
  791. if ( dlg )
  792. {
  793. dlg->Log ("FAILED", SAME_LINE );
  794. sprintf ( buffer2, "Failed to open \"%s\"", buffer );
  795. AfxMessageBox ( buffer2 );
  796. dlg->Log ( buffer2 );
  797. }
  798. }
  799. if ( dlg )
  800. {
  801. dlg->Ready();
  802. }
  803. return imports;
  804. }
  805. static int generate_noxstr ( TransDB *db, const char *filename, LangID langid, GNOPTIONS *options )
  806. {
  807. int ok = FALSE;
  808. FILE *file;
  809. if ( ! ( file = fopen ( filename, "wt" ) ))
  810. {
  811. goto error;
  812. }
  813. fprintf ( file, "// Generated by %s\n", AppTitle );
  814. fprintf ( file, "// Generated on %s %s\n\n\n", __DATE__, __TIME__ );
  815. {
  816. NoxLabel *label;
  817. NoxText *text;
  818. Translation *trans;
  819. ListSearch sh_label, sh_text;
  820. label = db->FirstLabel ( sh_label );
  821. while ( label )
  822. {
  823. text = label->FirstText ( sh_text );
  824. fprintf ( file, "\n\n%s\n", label->NameSB ());
  825. while ( text )
  826. {
  827. char *string;
  828. trans = text->GetTranslation ( langid );
  829. if ( !trans )
  830. {
  831. if ( langid == LANGID_US )
  832. {
  833. string = text->GetSB ();
  834. }
  835. else
  836. {
  837. if ( text->Len ())
  838. {
  839. if ( options->untranslated == GN_USEIDS )
  840. {
  841. string = buffer2;
  842. sprintf ( string, "%d", text->ID ());
  843. }
  844. else
  845. {
  846. string = text->GetSB();
  847. }
  848. }
  849. else
  850. {
  851. string = "";
  852. }
  853. }
  854. }
  855. else
  856. {
  857. string = trans->GetSB ();
  858. }
  859. if ( text->Len() == 0 )
  860. {
  861. string = "";
  862. }
  863. fprintf ( file, "\"%s\" %s\n", string, text->WaveSB() );
  864. text = label->NextText ( sh_text );
  865. }
  866. fprintf ( file, "END\n" );
  867. label = db->NextLabel ( sh_label );
  868. }
  869. ok = TRUE;
  870. }
  871. error:
  872. if ( file )
  873. {
  874. fclose ( file );
  875. }
  876. return ok;
  877. }
  878. static int writeCSFLabel ( FILE *file, NoxLabel *label )
  879. {
  880. int id = CSF_LABEL;
  881. int len = strlen ( label->NameSB() );
  882. int strings = label->NumStrings ();
  883. if ( fwrite ( &id, sizeof ( int ), 1, file ) != 1 )
  884. {
  885. return FALSE;
  886. }
  887. if ( fwrite ( &strings, sizeof ( int ), 1, file ) != 1 )
  888. {
  889. return FALSE;
  890. }
  891. if ( fwrite ( &len, sizeof ( int ), 1, file ) != 1 )
  892. {
  893. return FALSE;
  894. }
  895. if ( !len )
  896. {
  897. return FALSE;
  898. }
  899. if ( fwrite ( label->NameSB(), len, 1, file ) != 1 )
  900. {
  901. return FALSE;
  902. }
  903. return TRUE;
  904. }
  905. static int writeCSFString ( FILE *file, OLECHAR *string, char *wave, LANGINFO *linfo )
  906. {
  907. int id = CSF_STRING;
  908. int len ;
  909. int wlen = strlen ( wave );
  910. if ( wlen )
  911. {
  912. id = CSF_STRINGWITHWAVE;
  913. }
  914. wcscpy ( olebuf, string );
  915. StripSpaces ( olebuf );
  916. ConvertMetaChars ( olebuf );
  917. len = wcslen ( olebuf );
  918. {
  919. OLECHAR *ptr = olebuf;
  920. while ( *ptr)
  921. {
  922. *ptr = ~*ptr++;
  923. }
  924. }
  925. if ( fwrite ( &id, sizeof ( int ), 1, file ) != 1 )
  926. {
  927. return FALSE;
  928. }
  929. if ( fwrite ( &len, sizeof ( int ), 1, file ) != 1 )
  930. {
  931. return FALSE;
  932. }
  933. if ( len )
  934. {
  935. if ( fwrite ( olebuf, len*sizeof(OLECHAR), 1, file ) != 1 )
  936. {
  937. return FALSE;
  938. }
  939. }
  940. if ( wlen )
  941. {
  942. wlen++;
  943. if ( fwrite ( &wlen, sizeof ( int ), 1, file ) != 1 )
  944. {
  945. return FALSE;
  946. }
  947. if ( fwrite ( wave, wlen-1, 1, file ) != 1 )
  948. {
  949. return FALSE;
  950. }
  951. if ( fwrite ( linfo->character, 1, 1, file ) != 1 )
  952. {
  953. return FALSE;
  954. }
  955. }
  956. return TRUE;
  957. }
  958. static int generate_csf ( TransDB *db, const char *filename, LangID langid, GNOPTIONS *options )
  959. {
  960. CSF_HEADER header;
  961. int header_size;
  962. int ok = FALSE;
  963. FILE *file;
  964. LANGINFO *linfo = GetLangInfo ( langid);
  965. if ( ! ( file = fopen ( filename, "w+b" ) ))
  966. {
  967. goto error;
  968. }
  969. header.id = CSF_ID;
  970. header.version = CSF_VERSION;
  971. header.skip = 0;
  972. header.num_labels = 0;
  973. header.num_strings = 0;
  974. header.langid = langid;
  975. header_size = sizeof ( header );
  976. fseek ( file, header_size, SEEK_SET );
  977. {
  978. NoxLabel *label;
  979. NoxText *text;
  980. Translation *trans;
  981. ListSearch sh_label, sh_text;
  982. label = db->FirstLabel ( sh_label );
  983. while ( label )
  984. {
  985. text = label->FirstText ( sh_text );
  986. if ( !writeCSFLabel ( file, label ) )
  987. {
  988. goto error;
  989. }
  990. header.num_labels++;
  991. while ( text )
  992. {
  993. OLECHAR *string;
  994. trans = text->GetTranslation ( langid );
  995. if ( !trans )
  996. {
  997. if ( langid == LANGID_US )
  998. {
  999. string = text->Get ();
  1000. }
  1001. else
  1002. {
  1003. if ( text->Len ())
  1004. {
  1005. if ( options->untranslated == GN_USEIDS )
  1006. {
  1007. string = olebuf2;
  1008. swprintf ( string, L"%d", text->ID ());
  1009. }
  1010. else
  1011. {
  1012. string = text->Get();
  1013. }
  1014. }
  1015. else
  1016. {
  1017. string = L"";
  1018. }
  1019. }
  1020. }
  1021. else
  1022. {
  1023. string = trans->Get ();
  1024. }
  1025. if ( !writeCSFString ( file, string, text->WaveSB (), linfo ) )
  1026. {
  1027. goto error;
  1028. }
  1029. header.num_strings ++;
  1030. text = label->NextText ( sh_text );
  1031. }
  1032. label = db->NextLabel ( sh_label );
  1033. }
  1034. fseek ( file, 0, SEEK_SET );
  1035. if ( fwrite ( &header, header_size, 1, file ) != 1 )
  1036. {
  1037. goto error;
  1038. }
  1039. fseek ( file, 0, SEEK_END );
  1040. ok = TRUE;
  1041. }
  1042. error:
  1043. if ( file )
  1044. {
  1045. fclose ( file );
  1046. }
  1047. return ok;
  1048. }
  1049. int GenerateGameFiles ( TransDB *db, const char *filepattern, GNOPTIONS *options, LangID *languages, CNoxstringDlg *dlg)
  1050. {
  1051. static char filename[2*1024];
  1052. LangID langid;
  1053. int count= 0 ;
  1054. int num;
  1055. if ( dlg )
  1056. {
  1057. LangID *temp = languages;
  1058. num = 0;
  1059. while ( *temp++ != LANGID_UNKNOWN )
  1060. {
  1061. num++;
  1062. }
  1063. dlg->Log ( "" );
  1064. dlg->Status ( "Generating game files:" );
  1065. dlg->InitProgress ( num );
  1066. num = 0;
  1067. }
  1068. while ( (langid = *languages++) != LANGID_UNKNOWN )
  1069. {
  1070. LANGINFO *info;
  1071. TRNREPORT trnreport;
  1072. DLGREPORT dlgreport;
  1073. int dlgwarning;
  1074. int trnwarning;
  1075. int done;
  1076. info = GetLangInfo ( langid );
  1077. sprintf ( filename, "%s_%s.%s", filepattern, info->initials, options->format == GN_NOXSTR ? "str" : "csf" );
  1078. strlwr ( filename );
  1079. if ( dlg )
  1080. {
  1081. sprintf ( buffer, "Writing: %s - %s...", filename, GetLangName ( langid ));
  1082. dlg->Status ( buffer );
  1083. dlgwarning = db->ReportDialog ( &dlgreport, langid );
  1084. trnwarning = db->ReportTranslations ( &trnreport, langid );
  1085. }
  1086. if ( options->format == GN_NOXSTR )
  1087. {
  1088. done = generate_noxstr ( db, filename, langid, options );
  1089. }
  1090. else
  1091. {
  1092. done = generate_csf ( db, filename, langid, options );
  1093. }
  1094. if ( done )
  1095. {
  1096. count++;
  1097. if ( dlg )
  1098. {
  1099. if ( trnwarning || dlgwarning )
  1100. {
  1101. dlg->Log ( "WARNING", SAME_LINE );
  1102. if ( trnwarning )
  1103. {
  1104. int missing;
  1105. if ( (missing = trnreport.missing + trnreport.retranslate) )
  1106. {
  1107. sprintf ( buffer, "%d translation%s missing", missing, missing > 1 ? "s are" : " is" );
  1108. dlg->Log ( buffer );
  1109. }
  1110. if ( trnreport.too_big )
  1111. {
  1112. sprintf ( buffer, "%d string%s too big", trnreport.too_big, trnreport.too_big > 1 ? "s are" : " is" );
  1113. dlg->Log ( buffer );
  1114. }
  1115. if ( trnreport.bad_format )
  1116. {
  1117. sprintf ( buffer, "%d translation%s bad format", trnreport.bad_format, trnreport.bad_format > 1 ? "s have a" : " has a" );
  1118. dlg->Log ( buffer );
  1119. }
  1120. }
  1121. if ( dlgwarning )
  1122. {
  1123. if ( dlgreport.missing )
  1124. {
  1125. sprintf ( buffer, "%d dialog%s missing", dlgreport.missing, dlgreport.missing > 1 ? "s are" : " is" );
  1126. dlg->Log ( buffer );
  1127. }
  1128. if ( dlgreport.unresolved )
  1129. {
  1130. sprintf ( buffer, "%d dialog%s not verified", dlgreport.unresolved, dlgreport.unresolved> 1 ? "s are" : " is" );
  1131. dlg->Log ( buffer );
  1132. }
  1133. }
  1134. }
  1135. else
  1136. {
  1137. dlg->Log ( "OK", SAME_LINE );
  1138. }
  1139. }
  1140. }
  1141. else
  1142. {
  1143. if ( dlg )
  1144. {
  1145. dlg->Log ( "FAILED", SAME_LINE );
  1146. }
  1147. }
  1148. if ( dlg )
  1149. {
  1150. dlg->SetProgress ( ++num );
  1151. }
  1152. }
  1153. if ( dlg )
  1154. {
  1155. dlg->Ready ();
  1156. }
  1157. return count;
  1158. }
  1159. void ProcessWaves ( TransDB *db, const char *filename, CNoxstringDlg *dlg )
  1160. {
  1161. int imports = -1;
  1162. progress_dlg = dlg;
  1163. if ( dlg )
  1164. {
  1165. dlg->Log ("");
  1166. sprintf ( buffer, "Processing wavefile \"%s\"...", filename );
  1167. dlg->Status ( buffer );
  1168. }
  1169. if ( OpenWorkBook ( filename ) )
  1170. {
  1171. int row = 1;
  1172. int last_row = 1;
  1173. int matches = 0;
  1174. int unmatched = 0;
  1175. FILE *file = NULL;
  1176. char *ptr;
  1177. strcpy ( buffer, filename );
  1178. if ( (ptr = strchr ( buffer, '.' )) )
  1179. {
  1180. *ptr = 0;
  1181. }
  1182. strcat ( buffer, ".txt" );
  1183. if ( (file = fopen (buffer, "wt" )))
  1184. {
  1185. while ( row - last_row < 1000 )
  1186. {
  1187. NoxText *text;
  1188. GetString ( row, 'J' - 'A' + 1, olebuf );
  1189. wcslwr ( olebuf );
  1190. if ( wcsstr ( olebuf, L".wav" ) )
  1191. {
  1192. last_row = row;
  1193. fprintf ( file, "%S : ", olebuf );
  1194. GetString ( row, 'K' -'A' + 1, olebuf );
  1195. StripSpaces ( olebuf );
  1196. if ( (text = db->FindSubText ( olebuf ) ))
  1197. {
  1198. fprintf ( file, "%6d", text->LineNumber () );
  1199. }
  1200. else
  1201. {
  1202. fprintf ( file, "??????" );
  1203. }
  1204. fprintf ( file, " - \"%S\"\n", olebuf );
  1205. }
  1206. row++;
  1207. }
  1208. fclose ( file );
  1209. }
  1210. CloseWorkBook ( );
  1211. }
  1212. else
  1213. {
  1214. if ( dlg )
  1215. {
  1216. dlg->Log ("FAILED", SAME_LINE );
  1217. sprintf ( buffer2, "Failed to open \"%s\"", buffer );
  1218. AfxMessageBox ( buffer2 );
  1219. dlg->Log ( buffer2 );
  1220. }
  1221. }
  1222. if ( dlg )
  1223. {
  1224. dlg->Ready();
  1225. }
  1226. }
  1227. int GenerateReport ( TransDB *db, const char *filename, RPOPTIONS *options, LangID *languages, CNoxstringDlg *dlg)
  1228. {
  1229. LangID langid;
  1230. int count= 0 ;
  1231. int num;
  1232. FILE *file = NULL;
  1233. if ( dlg )
  1234. {
  1235. LangID *temp = languages;
  1236. num = 0;
  1237. while ( *temp++ != LANGID_UNKNOWN )
  1238. {
  1239. num++;
  1240. }
  1241. dlg->Log ( "" );
  1242. dlg->Status ( "Generating Report:" );
  1243. dlg->InitProgress ( num );
  1244. num = 0;
  1245. }
  1246. if ( ! ( file = fopen ( filename, "wt" )))
  1247. {
  1248. static char buffer[500];
  1249. sprintf ( "Unable to open file \"%s\".\n\nCannot create report!", filename);
  1250. AfxMessageBox ( buffer );
  1251. if ( dlg )
  1252. {
  1253. dlg->Log ( "FAILED", SAME_LINE );
  1254. dlg->Ready ();
  1255. }
  1256. return 0;
  1257. }
  1258. cb_file = file;
  1259. {
  1260. char date[50];
  1261. char time[50];
  1262. _strtime ( time );
  1263. _strdate ( date );
  1264. fprintf ( file, "Noxstring Report: %s %s\n", date, time);
  1265. }
  1266. while ( (langid = *languages++) != LANGID_UNKNOWN )
  1267. {
  1268. LANGINFO *info;
  1269. TRNREPORT tr_report;
  1270. DLGREPORT dlg_report;
  1271. info = GetLangInfo ( langid );
  1272. fprintf ( file, "\n\n%s Status:\n", info->name );
  1273. if ( options->translations )
  1274. {
  1275. int count;
  1276. count = db->ReportTranslations ( &tr_report, langid );
  1277. fprintf ( file, "\n\tText Summary: %s\n", info->name );
  1278. fprintf ( file, "\t-------------\n\n");
  1279. fprintf ( file, "\t\tErrors: %d\n", tr_report.errors);
  1280. if ( langid != LANGID_US )
  1281. {
  1282. fprintf ( file, "\t\tNot translated: %d\n", tr_report.missing);
  1283. fprintf ( file, "\t\tRetranslation: %d\n", tr_report.retranslate);
  1284. fprintf ( file, "\t\tTranslated: %d\n", tr_report.translated );
  1285. }
  1286. fprintf ( file, "\t\tTotal text: %d\n", tr_report.numstrings );
  1287. if ( count && count < options->limit )
  1288. {
  1289. fprintf ( file, "\n\tText Details: %s\n", info->name);
  1290. fprintf ( file, "\t------------\n\n" );
  1291. db->ReportTranslations ( &tr_report, langid, print_to_file );
  1292. }
  1293. }
  1294. if ( options->dialog )
  1295. {
  1296. int count;
  1297. count = db->ReportDialog ( &dlg_report, langid );
  1298. fprintf ( file, "\n\tDialog Summary: %s\n", info->name );
  1299. fprintf ( file, "\t-------------\n\n");
  1300. fprintf ( file, "\t\tMissing Audio: %d\n", dlg_report.missing);
  1301. fprintf ( file, "\t\tNot verified: %d\n", dlg_report.unresolved);
  1302. fprintf ( file, "\t\tVerified: %d\n", dlg_report.resolved);
  1303. fprintf ( file, "\t\tTotal dialog: %d\n", dlg_report.numdialog );
  1304. if ( count && count < options->limit )
  1305. {
  1306. fprintf ( file, "\n\tDialog Details: %s\n", info->name );
  1307. fprintf ( file, "\t------------\n\n" );
  1308. db->ReportDialog ( &dlg_report, langid, print_to_file );
  1309. }
  1310. }
  1311. if ( dlg )
  1312. {
  1313. dlg->SetProgress ( ++num );
  1314. }
  1315. }
  1316. if ( dlg )
  1317. {
  1318. dlg->Ready ();
  1319. }
  1320. fclose ( file );
  1321. return count;
  1322. }
  1323. int UpdateSentTranslations ( TransDB *db, const char *filename, CNoxstringDlg *dlg )
  1324. {
  1325. int imports = -1;
  1326. progress_dlg = dlg;
  1327. if ( dlg )
  1328. {
  1329. dlg->Log ("");
  1330. sprintf ( buffer, "Importing \"%s\"...", filename );
  1331. dlg->Status ( buffer );
  1332. }
  1333. if ( OpenWorkBook ( filename ) )
  1334. {
  1335. int num_strings;
  1336. LANGINFO *info;
  1337. num_strings = GetInt ( ROW_COUNT, COLUMN_COUNT );
  1338. GetString ( ROW_LANGUAGE, COLUMN_LANGUAGE, olebuf );
  1339. sprintf ( buffer, "%S", olebuf );
  1340. info = GetLangInfo ( buffer );
  1341. if ( !info )
  1342. {
  1343. if ( dlg )
  1344. {
  1345. AfxMessageBox ( "Import file is of an unknown language or is not a translation file" );
  1346. dlg->Log ( "FAILED", SAME_LINE );
  1347. dlg->Ready();
  1348. }
  1349. CloseWorkBook ();
  1350. return -1;
  1351. }
  1352. if ( dlg )
  1353. {
  1354. dlg->InitProgress ( num_strings );
  1355. progress_count = 0;
  1356. sprintf ( buffer, "...%s", info->name );
  1357. dlg->Log ( buffer, SAME_LINE );
  1358. }
  1359. imports = update_sent_trans ( db, info->langid, progress_cb, dlg );
  1360. CloseWorkBook ( );
  1361. }
  1362. else
  1363. {
  1364. if ( dlg )
  1365. {
  1366. dlg->Log ("FAILED", SAME_LINE );
  1367. sprintf ( buffer2, "Failed to open \"%s\"", buffer );
  1368. AfxMessageBox ( buffer2 );
  1369. dlg->Log ( buffer2 );
  1370. }
  1371. }
  1372. if ( dlg )
  1373. {
  1374. dlg->Ready();
  1375. }
  1376. return imports;
  1377. }