00001
00025 #include "color.h"
00026 #include "render.h"
00027 #include "text.h"
00028 #include "genconmac.h"
00029 #include "states.h"
00030 #include <SDL_ttf.h>
00031 #include <string.h>
00032 #include <assert.h>
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <locale.h>
00036 #include <errno.h>
00037
00038 #if defined(USE_GETTEXT) || defined(DOXYGEN)
00039 #include <wchar.h>
00040 #include <iconv.h>
00041 #if !defined(WIN32) || defined(DOXYGEN)
00042
00048 static iconv_t strconvdescr;
00055 static iconv_t strconvntou;
00062 static iconv_t strconvuton;
00063 #endif
00064 #endif
00065
00066 #ifndef TEXT_MAX_LINES
00067
00070 #define TEXT_MAX_LINES 16
00071 #endif
00072
00073 extern char binPath[128];
00074
00075
00076
00077
00078
00079 rtsa_char * strings[STRING_MAX];
00080
00081 RenderItem textItems[TEXTITEM_MAX];
00082
00088 static TTF_Font *fonts[FONT_MAX];
00089
00096 static int spaceWidth[FONT_MAX];
00097
00103 static int fontHeight[FONT_MAX];
00104
00105 Bool TextInit() {
00106 #ifdef USE_GETTEXT
00107 int loop;
00108 char *codeset = NULL, *localeDir = NULL, *localeName = NULL;
00109
00110 localeName = setlocale(LC_ALL, "");
00111 #ifndef NDEBUG
00112
00113 localeDir = bindtextdomain("rtsa", "./locale");
00114 #endif
00115
00116 textdomain("rtsa");
00117 #ifndef WIN32
00118
00119
00120 codeset = bind_textdomain_codeset("rtsa", "wchar_t");
00121
00122 strconvdescr = iconv_open("UTF-16", "wchar_t");
00123
00124 strconvntou = iconv_open("UTF-16BE", "wchar_t");
00125
00126 strconvuton = iconv_open("wchar_t", "UTF-16BE");
00127 #else
00128
00129
00130
00131 codeset = bind_textdomain_codeset("rtsa", "UTF-16LE");
00132 #endif
00133 #ifndef NDEBUG
00134 if (localeName) {
00135 #ifdef WIN32
00136 prnout(L"Using locale %S\n", localeName);
00137 #else
00138 prnout(L"Using locale %s\n", localeName);
00139 #endif
00140 }
00141 if (localeDir) {
00142 #ifdef WIN32
00143 prnout(L"Getting translated stings from path: %S\n", localeDir);
00144 #else
00145 prnout(L"Getting translated stings from path: %s\n", localeDir);
00146 #endif
00147 }
00148
00149 if (codeset) {
00150 #ifdef WIN32
00151
00152 prnout(L"Using %S character encoding\n", codeset);
00153 #else
00154 prnout(L"Using %s character encoding\n", codeset);
00155 #endif
00156 }
00157 else {
00158
00159 prnout(
00160 L"No character encoding set. Check your enviornment for problems.\n");
00161 }
00162 #endif
00163 #endif
00164
00165
00166
00167
00168 strings[STRING_REDTEAM] = _("Red team");
00169
00170
00171
00172 strings[STRING_BLUETEAM] = _("Blue team");
00173
00174
00175
00176
00177 strings[STRING_REDFLAGHELD] = _("Red flag held by blue team");
00178
00179
00180
00181
00182 strings[STRING_REDFLAGCAP] = _("Blue team scores!");
00183
00184
00185
00186 strings[STRING_REDWIN] = _("Red team wins!");
00187
00188
00189
00190
00191 strings[STRING_BLUEFLAGHELD] = _("Blue flag held by red team");
00192
00193
00194
00195
00196 strings[STRING_BLUEFLAGCAP] = _("Red team scores!");
00197
00198
00199
00200 strings[STRING_BLUEWIN] = _("Blue team wins!");
00201 #ifdef USE_GETTEXT
00202
00203 strings[STRING_TEAMKILL] = _("%ls shot teammate %ls");
00204
00205 strings[STRING_LOCALTEAMKILLER] = _("You shot %ls, a teammate!");
00206
00207 strings[STRING_LOCALTEAMKILLED] = _("Your teammate %ls shot you!");
00208
00209
00210 strings[STRING_KILL] = _("%ls shot %ls for a score of %d");
00211
00212
00213 strings[STRING_LOCALKILL] = _("You shot %ls, your score is %d");
00214 #else
00215 strings[STRING_TEAMKILL] = "%s shot teammate %s";
00216 strings[STRING_LOCALTEAMKILLER] = "You shot %s, a teammate!";
00217 strings[STRING_LOCALTEAMKILLED] = "Your teammate %s shot you!";
00218 strings[STRING_KILL] = "%s shot %s for a score of %d";
00219 strings[STRING_LOCALKILL] = "You shot %s, your score is %d";
00220 #endif
00221
00222
00223
00224 strings[STRING_RESPAWN] = _("Press fire to spawn your tank");
00225
00226
00227
00228
00229
00230 strings[STRING_TITLE] = _("Retro Tank Super Attack");
00231
00232 strings[STRING_AUTH] = _("by Jeff Jackowski (jeffj@ro.com)");
00233
00234
00235
00236 strings[STRING_TRANS] = _("translator");
00237 #ifdef USE_GETTEXT
00238
00239 strings[STRING_COPYRIGHT] = _("Copyright \xC2\xA9 2007");
00240 #else
00241 strings[STRING_COPYRIGHT] = "Copyright \xA9 2007";
00242 #endif
00243
00244
00245
00246
00247
00248 strings[STRING_GPL] = _( \
00249 "Retro Tank Super Attack comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions as defined by the GPL. For more details, see the GPL at: http://www.gnu.org/copyleft/gpl.html");
00250
00251 strings[STRING_CHOSETEAM] = _("Chose your team");
00252
00253
00254
00255 strings[STRING_FIREOPT] = _("Press fire for options");
00256
00257
00258 strings[STRING_FIRECONT] = _("Press fire to continue");
00259
00260
00261 strings[STRING_NETLOOKING] = _("Looking for server . . .");
00262
00263
00264 strings[STRING_NETCONTACT] = _("Contacting %s");
00265
00266
00267
00268 strings[STRING_NETRCVCFG] = _("Connected to %s, awaiting game options");
00269
00270
00271 strings[STRING_NETCLIENT] = _("Connected to %s");
00272
00273
00274 strings[STRING_NETCLIDISCONN] = _("Disconnecting from server . . .");
00275
00276
00277 strings[STRING_NETSERVER] = _("Running as server %s");
00278
00279
00280 strings[STRING_NETSRVDISCONN] = _("Disconnecting all clients . . .");
00281
00282
00283 strings[STRING_NETDENY] = _("Server %s denied the connection");
00284
00285
00286 strings[STRING_NETDISCONN] = _("Disconnected");
00287 #ifdef USE_GETTEXT
00288
00289
00290
00291
00292 strings[STRING_NETSEARCHERR] = _("Error prevented server discovery (%ls)");
00293
00294
00295 strings[STRING_NETSRVERR] = _("Error prevented running a server (%ls)");
00296
00297
00298 strings[STRING_NETCONERR] = \
00299 _("Error prevented connecting to the server (%ls)");
00300 #else
00301 strings[STRING_NETSEARCHERR] = "Error prevented server discovery (%s)";
00302 strings[STRING_NETSRVERR] = "Error prevented running a server (%s)";
00303 strings[STRING_NETCONERR] =
00304 "Error prevented connecting to the server (%s)";
00305 #endif
00306
00307
00308 strings[STRING_NETADDR] = _("Local address: %s");
00309
00310
00311 strings[STRING_NETSYNC] = _("Performing time synchronization");
00312
00313
00314
00315 strings[STRING_NETLAT] = _("Latency: %0.1lfms");
00316
00317
00318
00319 strings[STRING_DEFAULTNAME] = _("Anonymous");
00320
00321
00322
00323
00324
00325 strings[STRING_TIMEFORM] = _("%02d:%02d");
00326
00327
00328
00329 strings[STRING_TIMELEFT] = _("Time left:");
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 strings[STRING_BF_STAT] = \
00340 _("Finished parsing the battlefield configuration file successfully\nStats:\n Red Blue\nSpawn %3d %3d\nGoal %3d %3d\nObstacles %3d\n");
00341
00342
00343 strings[STRING_CMPLOPT] = \
00344 _("Compiled %i network messages that describe the game options\n");
00345 #ifdef USE_GETTEXT
00346
00347
00348
00349
00350
00351 strings[STRING_ERR_READ] = \
00352 _("Error in file %s at line %i: %ls");
00353
00354
00355
00356
00357 strings[STRING_ERR_PROC] = \
00358 _("Error while processing the battlefield: %ls");
00359 #else
00360 strings[STRING_ERR_READ] = \
00361 _("Error in file %s at line %i: %s");
00362 strings[STRING_ERR_PROC] = \
00363 _("Error while processing the battlefield: %s");
00364 #endif
00365
00366 strings[STRING_ERR_MEM] = _("Inadequate memory");
00367
00368 strings[STRING_ERR_FOPEN] = _("Could not open file: %s");
00369
00370
00371
00372 strings[STRING_ERR_EOFINC] = _("End of file in include statement");
00373
00374
00375
00376 strings[STRING_ERR_EOFNAME] = _("End of file in file name: %s");
00377
00378
00379
00380 strings[STRING_ERR_NAMELONG] = _("File name too long: %s...");
00381
00382
00383
00384
00385
00386 strings[STRING_ERR_FLDSMALL] = _("Field size, %dx%d, too small");
00387
00388
00389 strings[STRING_ERR_FLDLARGE] = _("Field size, %dx%d, too large");
00390
00391
00392
00393 strings[STRING_ERR_NOSIZE] = _("Battlefield size not specified");
00394
00395 strings[STRING_ERR_INVLDKEY] = _("Invalid keyword: %s");
00396
00397 strings[STRING_ERR_NOREDSPN] = _("Spawn area for red team not specified");
00398
00399 strings[STRING_ERR_NOBLSPN] = _("Spawn area for blue team not specified");
00400
00401
00402
00403
00404 strings[STRING_ERR_NOREDGOAL] = _("Goal area for red team not specified");
00405
00406
00407
00408
00409 strings[STRING_ERR_NOBLGOAL] = _("Goal area for blue team not specified");
00410
00411
00412
00413
00414 strings[STRING_ERR_BACKSLASH] \
00415 = _("Illegal backslashes used in file path: %s");
00416
00417 strings[STRING_ERR_IO] = _("I/O error while reading");
00418
00419 strings[STRING_ERR_EOL] = _("Token has line break");
00420
00421 strings[STRING_ERR_PARAM] \
00422 = _("Too few parameters for statement");
00423
00424
00425 strings[STRING_ERR_XYRANGE] = _("X or Y coordinate out of range");
00426
00427
00428 strings[STRING_ERR_WHRANGE] = _("Bad width or height");
00429
00430
00431 strings[STRING_ERR_BADOWN] = _("Bad team owning area: %s");
00432
00433
00434 strings[STRING_ERR_NONE] = _("No error");
00435
00436
00437 strings[STRING_ERR_WOULDBLOCK] = \
00438 _("Non-blocking operation waiting on data");
00439
00440
00441 strings[STRING_ERR_BADF] = _("Invalid file descriptor for the socket");
00442
00443
00444 strings[STRING_ERR_FAULT] = \
00445 _("Fault reading or writing to the given pointer(s)");
00446
00447
00448 strings[STRING_ERR_INTR] = _("Operation interrupted");
00449
00450 strings[STRING_ERR_INVAL] = _("Bad invalidness");
00451
00452
00453 strings[STRING_ERR_NOTSOCK] = _("Not a socket");
00454
00455
00456
00457
00458 strings[STRING_ERR_ADDRINUSE] = _("Address & port already in use");
00459
00460
00461 strings[STRING_ERR_NETDOWN] = _("Network is down");
00462
00463
00464 strings[STRING_ERR_NETUNREACH] = _("Network unreachable");
00465
00466
00467
00468 strings[STRING_ERR_CONNRESET] = _("Connection closed by remote end");
00469
00470
00471
00472
00473 strings[STRING_ERR_CONNREFUSED] = _("Previously sent data was refused");
00474
00475
00476 strings[STRING_ERR_HOSTUNREACH] = _("Host unreachable");
00477
00478
00479
00480 strings[STRING_ERR_HOSTLOOK] = _("Hostname lookup error: %s\n");
00481
00482
00483
00484
00485 strings[STRING_ERR_SDL] = _("Unable to initialize SDL: %s\n");
00486
00487
00488
00489
00490
00491 strings[STRING_ERR_VIDQ] = _("Video query failed: %s\n");
00492
00493
00494
00495
00496 strings[STRING_ERR_VIDMODE] = _("Unable to set video mode: %s\n");
00497
00498
00499
00500
00501
00502
00503 strings[STRING_ERR_TTFINIT] = _("Unable to initalize SDL_ttf: %s\n");
00504
00505
00506
00507 strings[STRING_ERR_RENDER] = \
00508 _("Unable to initalize the rendering system\n");
00509
00510
00511 strings[STRING_ERR_FNTOPEN] = _("Could not open font file: %s\n");
00512
00513
00514 strings[STRING_ERR_FNTINIT] = _("Unable to initalize the fonts\n");
00515
00516
00517
00518
00519 strings[STRING_ERR_OPENAUDIO] = _("Failed to open audio output: %s\n");
00520
00521
00522 strings[STRING_ERR_LOADSND] = _("Failed to load sound from file %s\n");
00523
00524
00525 strings[STRING_ERR_NOSNDS] = _("No sounds could be loaded\n");
00526
00527 strings[STRING_ERR_DEFAULT] = _("Some unbogus error");
00528
00529
00530 strings[STRING_STAT_SINGLEBUFF] = _("Video output is single-buffered\n");
00531
00532
00533 strings[STRING_STAT_DOUBLEBUFF] = _("Video output is double-buffered\n");
00534
00535
00536 strings[STRING_STAT_NOHWACCEL] = \
00537 _("Video output lacks hardware acceleration\n");
00538
00539
00540 strings[STRING_STAT_HWACCEL] = _("Video output is hardware accelerated\n");
00541
00542
00543
00544 strings[STRING_STAT_OUTSYSMEM] = \
00545 _("Video output surface is stored in system memory\n");
00546
00547
00548
00549
00550 strings[STRING_STAT_OUTGRPMEM] = \
00551 _("Video output surface is stored in the graphics hardware's memory\n");
00552
00553
00554 strings[STRING_STAT_VIDDRNAME] = _("Video driver is %s\n");
00555
00556
00557
00558
00559
00560
00561 strings[STRING_STAT_JOYSTICK] = \
00562 _("Using joystick %s:\n\tAxes: %d\n\tButtons: %d\n");
00563
00564
00565 strings[STRING_STAT_NOAUDIO] = \
00566 _("Could not initialize audio; continuing without sound\n");
00567
00568
00569 strings[STRING_STAT_ENTERSTATE] = _("Entering state loop\n");
00570
00571
00572 strings[STRING_STAT_EXITSTATE] = _("Exited state loop; shutting down\n");
00573
00574 #ifdef USE_GETTEXT
00575
00576
00577 if (strcmp((char*)(strings[STRING_REDTEAM]), "Red team") == 0) {
00578 char *src;
00579 wchar_t *dest;
00580 size_t srcLen, destLen;
00581
00582 #ifndef WIN32
00583 iconv_t descr = iconv_open("wchar_t", "UTF-8");
00584 #else
00585 iconv_t descr = iconv_open("UTF-16LE", "UTF-8");
00586 #endif
00587
00588 if (descr == (iconv_t)-1) {
00589 #if defined(WIN32) && !defined(NDEBUG)
00590 int err = errno;
00591 #endif
00592
00593 prnfile(stderr,
00594 L"Cannot convert internal strings to wide character strings\nError code: %d\n",
00595 errno);
00596 exit(1);
00597 }
00598 #ifndef NDEBUG
00599 prnout(
00600 L"Translated strings were not loaded; using internal English strings instead\n");
00601 #endif
00602
00603 for (loop = 0; loop < STRING_MAX; loop++) {
00604
00605 srcLen = (int)strlen(src = (char*)strings[loop]);
00606
00607 strings[loop] = dest = malloc(
00608 destLen = (srcLen + 1) * sizeof(wchar_t));
00609
00610 iconv(descr, &src, &srcLen, (char**)&dest, &destLen);
00611 *dest = 0;
00612 }
00613 iconv_close(descr);
00614 }
00615 #ifdef WIN32
00616
00617 {
00618 rtsa_char buff[1024], **src;
00619 int srcInd, destInd;
00620 Bool typeStart;
00621
00622 for (src = strings, loop = 0; loop < STRING_MAX; src++, loop++) {
00623 typeStart = FALSE;
00624
00625 for (srcInd = destInd = 0; (*src)[srcInd] != 0;
00626 srcInd++, destInd++) {
00627
00628 if (typeStart && ((*src)[srcInd] == 's')) {
00629
00630 buff[destInd] = 'S';
00631 typeStart = FALSE;
00632 continue;
00633 }
00634
00635 else if (typeStart && ((*src)[srcInd] == 'l') &&
00636 ((*src)[srcInd + 1] == 's')) {
00637
00638 buff[destInd] = 's';
00639
00640 srcInd++;
00641 typeStart = FALSE;
00642 continue;
00643 }
00644
00645 else if ((*src)[srcInd] == '%') {
00646
00647 typeStart = TRUE;
00648 }
00649
00650
00651 else if (((*src)[srcInd] != '$') &&
00652 !iswdigit((*src)[srcInd])) {
00653
00654 typeStart = FALSE;
00655 }
00656
00657 buff[destInd] = (*src)[srcInd];
00658 }
00659
00660 buff[destInd] = 0;
00661
00662 (*src) = malloc(sizeof(wchar_t) * (destInd + 1));
00663
00664 memcpy(*src, buff, sizeof(wchar_t) * (destInd + 1));
00665 }
00666 }
00667
00668 #endif
00669
00670 #endif
00671
00672 return TRUE;
00673 }
00674
00675 Bool FontInit() {
00676 char path[128];
00677 int len, loop;
00678 const Uint16 space[] = { ' ', 0 };
00679
00683
00684 memset(textItems, 0, sizeof(textItems));
00685
00686 strcpy(path, binPath);
00687 len = (int)strlen(path);
00688 strcpy(path + len, "font.ttf");
00689
00690 if ((fonts[FONT_MESSAGE] = TTF_OpenFont(path, 32)) == NULL) {
00691 goto FontInit_noFont;
00692 }
00693 if ((fonts[FONT_SCORE] = TTF_OpenFont(path, 16)) == NULL) {
00694 goto FontInit_noFont;
00695 }
00696 if ((fonts[FONT_PLAYER] = TTF_OpenFont(path, 10)) == NULL) {
00697 goto FontInit_noFont;
00698 }
00699
00700 for (loop = 0; loop < FONT_MAX; loop++) {
00701 TTF_SizeUNICODE(fonts[loop], space, &spaceWidth[loop], NULL);
00702 fontHeight[loop] = TTF_FontLineSkip(fonts[loop]);
00703 }
00704 return TRUE;
00705
00706 FontInit_noFont:
00707
00708 prnfile(stderr, strings[STRING_ERR_FNTOPEN], path);
00709 return FALSE;
00710 }
00711
00729 static Bool TextSetup(int startStr, int startInd, int endInd, int font,
00730 SDL_Color color) {
00731 int loop, strInd;
00732
00733 for (strInd = startStr, loop = startInd; loop < endInd;
00734 strInd++, loop++) {
00735 #ifdef USE_GETTEXT
00736 #ifndef WIN32
00737
00738 Uint16 destStr[96];
00739 char *src = (char*)strings[strInd], *dest = (char*)destStr;
00740 size_t srcLen = (wcslen((wchar_t*)src) + 1) * sizeof(rtsa_char);
00741 size_t destLen = sizeof(destStr);
00742 iconv(strconvdescr, &src, &srcLen, &dest, &destLen);
00743 *dest = 0;
00744
00745 if ((textItems[loop].data = TTF_RenderUNICODE_Blended(fonts[font],
00746 destStr, color)) == NULL)
00747 #else
00748
00749 if ((textItems[loop].data = TTF_RenderUNICODE_Blended(fonts[font],
00750 strings[strInd], color)) == NULL)
00751 #endif
00752 #else
00753
00754 if ((textItems[loop].data = TTF_RenderText_Blended(fonts[font],
00755 strings[strInd], color)) == NULL)
00756 #endif
00757 {
00758
00759 return FALSE;
00760 }
00761
00762 textItems[loop].loc.w = ((SDL_Surface*)textItems[loop].data)->w;
00763 textItems[loop].loc.h = ((SDL_Surface*)textItems[loop].data)->h;
00764
00765 textItems[loop].renderer = GenericSurfaceRenderer;
00766
00767 if (textItems[loop].parent == NULL) {
00768 AddRenderItem(&(textItems[loop]), LAYER_TEXT);
00769 }
00770 }
00771 return TRUE;
00772 }
00773
00774 Bool TextSetupStateSplash() {
00775
00776 if (TextSetup(STRING_TITLE, TEXTITEM_TITLE, TEXTITEM_TITLE + 1,
00777 FONT_MESSAGE, colorFmtInd[COLOR_TEXT]) && TextSetup(STRING_AUTH,
00778 TEXTITEM_AUTH, TEXTITEM_AUTH + 1, FONT_SCORE,
00779 colorFmtInd[COLOR_TEXT]) && TextSetup(STRING_COPYRIGHT, TEXTITEM_COPYRIGHT,
00780 TEXTITEM_COPYRIGHT + 1, FONT_PLAYER, colorFmtInd[COLOR_TEXT]) &&
00781 TextRenderString(&textItems[TEXTITEM_GPL], FONT_PLAYER, 340,
00782 colorFmtInd[COLOR_TEXT], strings[STRING_GPL])) {
00783
00784 if (textItems[TEXTITEM_GPL].parent == NULL) {
00785 AddRenderItem(&(textItems[TEXTITEM_GPL]), LAYER_TEXT);
00786 }
00787
00788 #ifdef USE_GETTEXT
00789 if (wcscmp(L"translator", strings[STRING_TRANS]) != 0)
00790 #else
00791 if (strcmp("translator", strings[STRING_TRANS]) != 0)
00792 #endif
00793 {
00794
00795 if (!TextRenderString(&textItems[TEXTITEM_TRANS], FONT_SCORE, 340,
00796 colorFmtInd[COLOR_TEXT], strings[STRING_TRANS])) {
00797
00798 return FALSE;
00799 }
00800
00801 if (textItems[TEXTITEM_TRANS].parent == NULL) {
00802 AddRenderItem(&(textItems[TEXTITEM_TRANS]), LAYER_TEXT);
00803 }
00804 }
00805
00806 return TRUE;
00807 }
00808
00809 return FALSE;
00810 }
00811
00812 Bool TextSetupStateMenu() {
00813
00814 if (TextSetup(STRING_TITLE, TEXTITEM_TITLE, TEXTITEM_TITLE + 1,
00815 FONT_MESSAGE, colorFmtInd[COLOR_TEXT]) && TextSetup(STRING_CHOSETEAM,
00816 TEXTITEM_CHOSETEAM, TEXTITEM_FIREOPT + 1, FONT_SCORE,
00817 colorFmtInd[COLOR_TEXT])) {
00818
00819 return TRUE;
00820 }
00821
00822 return FALSE;
00823 }
00824
00825 Bool TextSetupStatePlay() {
00826
00827 if (TextSetup(STRING_REDTEAM, TEXTITEM_REDTEAM, TEXTITEM_BLUETEAM + 1,
00828 FONT_SCORE, colorFmtInd[COLOR_TEXT]) && TextSetup(STRING_RESPAWN,
00829 TEXTITEM_RESPAWN, TEXTITEM_RESPAWN + 1, FONT_MESSAGE,
00830 colorFmtInd[COLOR_TEXT])) {
00831
00832 return TRUE;
00833 }
00834
00835 return FALSE;
00836 }
00837
00838 void TextUnsetState() {
00839 int loop;
00840
00841 for (loop = 0; loop < TEXTITEM_MAX; loop++) {
00842
00843 if (textItems[loop].data) {
00844
00845 SDL_FreeSurface(textItems[loop].data);
00846 }
00847
00848 if (textItems[loop].parent != NULL) {
00849
00850 RemoveRenderItem(&(textItems[loop]));
00851 }
00852 }
00853
00854 memset(textItems, 0, sizeof(textItems));
00855 }
00856
00857 void TextUninit() {
00858 int loop;
00859 #ifdef USE_GETTEXT
00860 char *test = "Red team";
00861 #endif
00862
00863 TextUnsetState();
00864
00865 for (loop = 0; loop < FONT_MAX; loop++) {
00866
00867 TTF_CloseFont(fonts[loop]);
00868 }
00869 #ifdef USE_GETTEXT
00870
00871 test = gettext(test);
00872 if (strcmp(test, "Red team") == 0) {
00873
00874 for (loop = 0; loop < STRING_MAX; loop++) {
00875 free(strings[loop]);
00876 }
00877 }
00878 #ifndef WIN32
00879 iconv_close(strconvdescr);
00880 iconv_close(strconvntou);
00881 iconv_close(strconvuton);
00882 #endif
00883 #endif
00884 }
00885
00886 int TextNativeToUTF16(Uint16 *dest, size_t destlen, rtsa_char *src,
00887 size_t srclen) {
00888 size_t len;
00889
00890 assert(destlen > srclen);
00891
00892 srclen *= sizeof(rtsa_char);
00893 destlen <<= 1;
00894 #if defined(USE_GETTEXT) && !defined(WIN32)
00895 len = destlen;
00896
00897 if (iconv(strconvntou, (char**)&src, &srclen, (char**)&dest, &len) < 0) {
00898
00899 return -1;
00900 }
00901
00902 *dest = 0;
00903
00904 return (destlen - len) >> 1;
00905 #else
00906 #ifndef USE_GETTEXT
00907 srclen <<= 1;
00908 #endif
00909
00910 for (len = 0; len < srclen; len += 2, src++) {
00911
00912 #ifdef USE_GETTEXT
00913 ((Uint8*)(dest))[len] = *src >> 8;
00914 #else
00915 ((Uint8*)(dest))[len] = 0;
00916 #endif
00917 ((Uint8*)(dest))[len + 1] = *src & 0xFF;
00918 if (*src == 0) {
00919
00920 return (int)len >> 1;
00921 }
00922 }
00923
00924 dest[srclen] = 0;
00925
00926 return (int)len >> 1;
00927 #endif
00928 }
00929
00930 int TextUTF16toNative(rtsa_char *dest, size_t destlen, Uint16 *src,
00931 size_t srclen) {
00932 size_t len;
00933
00934 assert(destlen > srclen);
00935
00936 srclen <<= 1;
00937 destlen *= sizeof(rtsa_char);
00938 #if defined(USE_GETTEXT) && !defined(WIN32)
00939 len = destlen;
00940
00941 assert(destlen > (srclen << 1));
00942 if (iconv(strconvuton, (char**)&src, &srclen, (char**)&dest, &len) < 0) {
00943
00944 return -1;
00945 }
00946
00947 *dest = 0;
00948
00949 return (destlen - len) / sizeof(rtsa_char);
00950 #else
00951
00952
00953 for (len = 0; len < srclen; len += 2, dest++) {
00954
00955 #ifdef USE_GETTEXT
00956
00957 *dest = (((Uint8*)(src))[len] << 8) | ((Uint8*)(src))[len + 1];
00958 #else
00959
00960 if (((Uint8*)(src))[len] > 0) {
00961
00962
00963 *dest = '?';
00964 }
00965 else {
00966
00967 *dest = ((Uint8*)(src))[len + 1];
00968 }
00969 #endif
00970 if (*dest == 0) {
00971
00972 return (int)len >> 1;
00973 }
00974 }
00975
00976 *dest = 0;
00977
00978 return (int)len >> 1;
00979 #endif
00980 }
00981
00982 void TextSetWindowTitle() {
00991 #ifdef USE_GETTEXT
00992
00993 const SDL_version * const ver = SDL_Linked_Version();
00994
00995 if ((ver->major >= 1) && (ver->minor >= 2) && (ver->patch >= 10)) {
00996 char buff[128], *buffPtr = buff, *inPtr = (char*)strings[STRING_TITLE];
00997 size_t res, inlen, outlen = 128;
00998
00999 iconv_t titleconv;
01000
01001 #ifdef WIN32
01002 titleconv = iconv_open("UTF-8", "UTF-16LE");
01003 #else
01004 titleconv = iconv_open("UTF-8", "wchar_t");
01005 #endif
01006 inlen = (rtsa_strlen(strings[STRING_TITLE]) + 1) * sizeof(rtsa_char);
01007
01008 res = iconv(titleconv, &inPtr, &inlen, &buffPtr, &outlen);
01009
01010 iconv_close(titleconv);
01011
01012 if ((res >= 0) && (inlen == 0)) {
01013
01014 SDL_WM_SetCaption(buff, NULL);
01015
01016 return;
01017 }
01018 }
01019 #endif
01020
01021
01022 SDL_WM_SetCaption("Retro Tank Super Attack", NULL);
01023 }
01024
01025 Bool TextRenderString(RenderItem *text, int font, int maxwidth, SDL_Color color,
01026 const rtsa_char *format, ...) {
01027 va_list args;
01028 Bool res;
01029
01030 va_start(args, format);
01031
01032 res = TextRenderStringV(text, font, maxwidth, color, format, args);
01033
01034 va_end(args);
01035 return res;
01036 }
01037
01038 Bool TextRenderStringV(RenderItem *text, int font, int maxwidth,
01039 SDL_Color color, const rtsa_char *format, va_list args) {
01040 #if !defined(WIN32) && defined(USE_GETTEXT)
01041 rtsa_char wstring[512];
01042 #endif
01043 rtsa_outchar string[512];
01044 int len;
01045 assert(font < FONT_MAX);
01046 assert(text != NULL);
01047 text->renderer = NULL;
01048
01049 #ifdef USE_GETTEXT
01050 #if defined(_MSC_VER)
01051 #if (_MSC_VER <= 1310)
01052
01053 if ((len = _vsnwprintf(string, 511, format, args)) <= 0) {
01054 return FALSE;
01055 }
01056 string[511] = 0;
01057 #else
01058
01059 if ((len = _vswprintf_p(string, 512, format, args)) <= 0) {
01060 return FALSE;
01061 }
01062 #endif
01063 #else
01064
01065 if ((len = vswprintf(wstring, 512, format, args)) > 0) {
01066 size_t outsize = sizeof(string);
01067 size_t inbytes = len * sizeof(rtsa_char);
01068 rtsa_char *inbuff = wstring;
01069 Uint16 *outbuff = string;
01070
01071 if (iconv(strconvdescr, (char**)&inbuff, &inbytes,
01072 (char**)&outbuff, &outsize) < 0) {
01073 return FALSE;
01074 }
01075 *outbuff = 0;
01076 }
01077 else {
01078 return FALSE;
01079 }
01080 #endif
01081 #else
01082
01083 if ((len = vsprintf(string, format, args)) <= 0) {
01084 return FALSE;
01085 }
01086 #endif
01087
01088
01089 va_end(args);
01090
01091
01092 if (text->data != NULL) {
01093
01094 SDL_FreeSurface(text->data);
01095 }
01096
01097
01098 if (maxwidth > 0) {
01099 SDL_Surface *lineSurf[TEXT_MAX_LINES], **surface;
01100 SDL_Rect dest;
01101 int start = 0, end = 0, pos = 0, greatestWidth = 0, lines = 0, width,
01102 newWidth, destind;
01103
01104 while ((pos < len) && (lines < TEXT_MAX_LINES)) {
01105
01106 width = 0;
01107 do {
01108
01109 for (pos = end + 1; (pos < len) && (string[pos] != ' '); pos++);
01110
01111 if (string[pos] == ' ') {
01112
01113 string[pos] = 0;
01114 }
01115
01116 if (SizeTTF(fonts[font], &string[start], &newWidth, NULL) < 0) {
01117
01118 goto TRS_LinesFail;
01119 }
01120
01121 if (pos < len) {
01122 string[pos] = ' ';
01123 }
01124
01125 if ((newWidth <= maxwidth) || (start == end)) {
01126
01127 end = pos;
01128 width = newWidth;
01129 }
01130
01131 else {
01132 break;
01133 }
01134 } while ((pos < len) && (width < maxwidth));
01135
01136 string[end] = 0;
01137
01138 if ((lineSurf[lines++] =
01139 RenderTTF(fonts[font], &string[start], color)) == NULL) {
01140
01141 goto TRS_LinesFail;
01142 }
01143
01144 if (lineSurf[lines-1]->w > greatestWidth) {
01145 greatestWidth = lineSurf[lines-1]->w;
01146 }
01147
01148 if (end < len) {
01149 end++;
01150 }
01151 start = pos = end;
01152 }
01153
01154 if (lines == 0) {
01155 return FALSE;
01156 }
01157
01158 if (lines == 1) {
01159
01160 text->data = lineSurf[0];
01161 goto TRS_End;
01162 }
01163
01164 if ((text->data = SDL_CreateRGBSurface(SDL_SWSURFACE,
01165 text->loc.w = greatestWidth, text->loc.h = lines * fontHeight[font], 32,
01166
01167 lineSurf[0]->format->Rmask, lineSurf[0]->format->Gmask,
01168 lineSurf[0]->format->Bmask, lineSurf[0]->format->Amask
01169 )) == NULL) {
01170
01171 goto TRS_LinesFail;
01172 }
01173
01174 dest.y = 0;
01175 destind = 0;
01176 for (surface = &lineSurf[0]; lines > 0; lines--, surface++) {
01177 int linecpy, srcind = 0;
01178
01179 dest.x = (greatestWidth >> 1) - ((*surface)->w >> 1);
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 for (linecpy = fontHeight[font]; linecpy > 0; linecpy--, dest.y++) {
01197
01198 memcpy(
01199 ((int*)(((SDL_Surface*)(text->data))->pixels)) + dest.x + destind,
01200 ((int*)((*surface)->pixels)) + srcind, (*surface)->w << 2);
01201
01202 srcind += (*surface)->w;
01203 destind += ((SDL_Surface*)(text->data))->w;
01204 }
01205
01206 SDL_FreeSurface(*surface);
01207 }
01208
01209
01210
01211
01212
01213
01214
01215
01216 text->renderer = GenericSurfaceRenderer;
01217
01218 return TRUE;
01219
01220 TRS_LinesFail:
01221
01222 for (surface = &lineSurf[0]; lines > 0; lines--, surface++) {
01223 SDL_FreeSurface(*surface);
01224 }
01225
01226 return FALSE;
01227 }
01228
01229
01230 if ((text->data = RenderTTF(fonts[font], string, color)) == NULL) {
01231
01232 return FALSE;
01233 }
01234 TRS_End:
01235
01236 text->loc.w = ((SDL_Surface*)text->data)->w;
01237 text->loc.h = ((SDL_Surface*)text->data)->h;
01238
01239 text->renderer = GenericSurfaceRenderer;
01240
01241 return TRUE;
01242 }
01243