diff --git a/configure.ac b/configure.ac index 2aa44b8..de100ca 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ PKG_PROG_PKG_CONFIG AC_PROG_CC AC_PROG_INSTALL -STARFIGHTER_CFLAGS="-DVERSION=\\\"$PACKAGE_VERSION\\\"" +STARFIGHTER_CPPFLAGS="-DVERSION=\\\"$PACKAGE_VERSION\\\" -Wall -Wformat-truncation=0" # Checks for libraries. AC_SEARCH_LIBS([atanf], [m]) @@ -27,7 +27,7 @@ PKG_CHECK_EXISTS([SDL2_mixer], [ PKG_CHECK_MODULES([SDL], [sdl2 SDL2_image SDL2_mixer SDL2_ttf]) ], [ PKG_CHECK_MODULES([SDL], [sdl2 SDL2_image SDL2_mixer]) - STARFIGHTER_CFLAGS="$STARFIGHTER_CFLAGS -DNOFONT" + STARFIGHTER_CPPFLAGS="$STARFIGHTER_CPPFLAGS -DNOFONT" echo "Note: SDL_ttf not found; Unicode will not be supported." ]) ], [ @@ -35,41 +35,47 @@ PKG_CHECK_EXISTS([SDL2_mixer], [ PKG_CHECK_MODULES([SDL], [sdl2 SDL2_image SDL2_ttf]) ], [ PKG_CHECK_MODULES([SDL], [sdl2 SDL2_image]) - STARFIGHTER_CFLAGS="$STARFIGHTER_CFLAGS -DNOFONT" + STARFIGHTER_CPPFLAGS="$STARFIGHTER_CPPFLAGS -DNOFONT" echo "Note: SDL_ttf not found; Unicode will not be supported." ]) - STARFIGHTER_CFLAGS="$STARFIGHTER_CFLAGS -DNOSOUND" + STARFIGHTER_CPPFLAGS="$STARFIGHTER_CPPFLAGS -DNOSOUND" echo "Note: SDL_mixer not found; audio will not be supported." ]) PKG_CHECK_MODULES([PANGO], [pango], [ ], [ - STARFIGHTER_CFLAGS="$STARFIGHTER_CFLAGS -DNOFONT" + STARFIGHTER_CPPFLAGS="$STARFIGHTER_CPPFLAGS -DNOFONT" echo "Note: Pango not found; Unicode will not be supported." ]) AC_ARG_VAR([SF_SCREEN_WIDTH], [The width of the game window in pixels]) AC_ARG_VAR([SF_SCREEN_HEIGHT], [The height of the game window in pixels]) +AC_ARG_VAR([SF_NOFONT], [Set to 1 to manually force the compiler not to include font/Unicode support]) AC_ARG_VAR([SF_RUN_IN_PLACE], [Set to 1 to compile Starfighter to run in-place (instead of installing)]) AS_IF([test -n "$SF_SCREEN_WIDTH"], [ - STARFIGHTER_CFLAGS="$STARFIGHTER_CFLAGS -DSCREEN_WIDTH=$SF_SCREEN_WIDTH" + STARFIGHTER_CPPFLAGS="$STARFIGHTER_CPPFLAGS -DSCREEN_WIDTH=$SF_SCREEN_WIDTH" echo "Using default screen width of $SF_SCREEN_WIDTH" ], [ echo "Using built-in screen width default" ]) AS_IF([test -n "$SF_SCREEN_HEIGHT"], [ - STARFIGHTER_CFLAGS="$STARFIGHTER_CFLAGS -DSCREEN_HEIGHT=$SF_SCREEN_HEIGHT" + STARFIGHTER_CPPFLAGS="$STARFIGHTER_CPPFLAGS -DSCREEN_HEIGHT=$SF_SCREEN_HEIGHT" echo "Using default screen height of $SF_SCREEN_HEIGHT" ], [ echo "Using built-in screen height default" ]) +AS_IF([test -n "$SF_NOFONT"], [ + STARFIGHTER_CPPFLAGS="$STARFIGHTER_CPPFLAGS -DNOFONT" + echo "Font/Unicode support manually disabled" +]) + AS_IF([test -n "$SF_RUN_IN_PLACE"], [ echo "Preparing a run-in-place build" ]) AM_CONDITIONAL([RUN_IN_PLACE], [test -n "$SF_RUN_IN_PLACE"]) -AC_SUBST([STARFIGHTER_CFLAGS]) +AC_SUBST([STARFIGHTER_CPPFLAGS]) # Checks for header files. AC_CHECK_HEADERS([ctype.h errno.h libintl.h locale.h stdio.h stdlib.h string.h time.h math.h pwd.h sys/stat.h unistd.h]) diff --git a/src/Makefile.am b/src/Makefile.am index 273078f..c4f0431 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,9 +6,9 @@ bin_PROGRAMS = starfighter if RUN_IN_PLACE -starfighter_CPPFLAGS = $(STARFIGHTER_CFLAGS) -Wall -Wformat-truncation=0 +starfighter_CPPFLAGS = $(STARFIGHTER_CPPFLAGS) else -starfighter_CPPFLAGS = $(STARFIGHTER_CFLAGS) -DDATADIR=\"$(pkgdatadir)\" -Wall -Wformat-truncation=0 +starfighter_CPPFLAGS = $(STARFIGHTER_CPPFLAGS) -DDATADIR=\"$(pkgdatadir)\" endif starfighter_CFLAGS = $(SDL_CFLAGS) $(PANGO_CFLAGS) diff --git a/src/alien.c b/src/alien.c index 9d4f61a..bb6eea4 100644 --- a/src/alien.c +++ b/src/alien.c @@ -2113,7 +2113,7 @@ void alien_destroy(Object *alien, Object *attacker) { /// Dialog (Kline Kethlan) /// Used when Kline is killed in the Venus mission. - radio_setMessage(FS_KLINE, "It was an honor... to have fought you...", 1); + radio_setMessage(FS_KLINE, _("It was an honor... to have fought you..."), 1); alien->dx = alien->dy = 0; alien->shield = -150; } diff --git a/src/game.c b/src/game.c index 70c32e9..9a6e782 100644 --- a/src/game.c +++ b/src/game.c @@ -313,20 +313,27 @@ static void game_doCollectables() case P_CASH: game.cash += collectable->value; game.cashEarned += collectable->value; - snprintf(temp, STRMAX_SHORT, "Got $%d ", collectable->value); + snprintf(temp, STRMAX_SHORT, ngettext( + /// "%d" must be retained. It is replaced with the amount of money that + /// was picked up. + "Got $%d", + "Got $%d", + collectable->value), collectable->value); break; case P_ROCKET: LIMIT_ADD(player.ammo[1], collectable->value, 0, game.maxRocketAmmo); if (player.ammo[1] == game.maxRocketAmmo) - strcpy(temp, "Rocket Ammo at Maximum"); + strcpy(temp, _("Rocket Ammo at Maximum")); else { - if (collectable->value > 1) - snprintf(temp, STRMAX_SHORT, "Got %d rockets", collectable->value); - else - strcpy(temp, "Got a rocket"); + snprintf(temp, STRMAX_SHORT, ngettext( + /// "%d" must be retained. It is replaced with the number of rockets + /// picked up. + "Got %d rocket", + "Got %d rockets", + collectable->value), collectable->value); } game.rocketPickups += collectable->value; break; @@ -334,7 +341,7 @@ static void game_doCollectables() case P_SHIELD: LIMIT_ADD(player.shield, 10, 0, player.maxShield); game.shieldPickups ++; - strcpy(temp, "Restored 10 shield points"); + strcpy(temp, _("Restored 10 shield points")); break; case P_PLASMA_RATE: @@ -347,11 +354,11 @@ static void game_doCollectables() weapons[W_PLAYER_WEAPON].reload[0] - 2); if (weapons[W_PLAYER_WEAPON].reload[0] <= rate2reload[game.maxPlasmaRate]) - strcpy(temp, "Firing rate already at maximum"); + strcpy(temp, _("Firing rate already at maximum")); else { weapons[W_PLAYER_WEAPON].reload[0] -= 2; - strcpy(temp, "Firing rate increased"); + strcpy(temp, _("Firing rate increased")); } } else if ((game.area != MISN_INTERCEPTION) || @@ -362,16 +369,16 @@ static void game_doCollectables() 0, game.maxPlasmaAmmo); if (weapons[W_PLAYER_WEAPON].reload[0] <= rate2reload[game.maxPlasmaRate]) - strcpy(temp, "Firing rate already at maximum"); + strcpy(temp, _("Firing rate already at maximum")); else { weapons[W_PLAYER_WEAPON].reload[0] -= 2; - strcpy(temp, "Firing rate increased"); + strcpy(temp, _("Firing rate increased")); } } else { - strcpy(temp, "Upgrade failed (no plasma ammo)"); + strcpy(temp, _("Upgrade failed (no plasma ammo)")); } break; @@ -384,11 +391,11 @@ static void game_doCollectables() game.maxPlasmaOutput, weapons[W_PLAYER_WEAPON].ammo[0] + 1); if (weapons[W_PLAYER_WEAPON].ammo[0] >= game.maxPlasmaOutput) - strcpy(temp, "Plasma output already at maximum"); + strcpy(temp, _("Plasma output already at maximum")); else { weapons[W_PLAYER_WEAPON].ammo[0]++; - strcpy(temp, "Plasma output increased"); + strcpy(temp, _("Plasma output increased")); } } else if ((game.area != MISN_INTERCEPTION) || @@ -399,16 +406,16 @@ static void game_doCollectables() 0, game.maxPlasmaAmmo); if (weapons[W_PLAYER_WEAPON].ammo[0] >= game.maxPlasmaOutput) - strcpy(temp, "Plasma output already at maximum"); + strcpy(temp, _("Plasma output already at maximum")); else { weapons[W_PLAYER_WEAPON].ammo[0]++; - strcpy(temp, "Plasma output increased"); + strcpy(temp, _("Plasma output increased")); } } else { - strcpy(temp, "Upgrade failed (no plasma ammo)"); + strcpy(temp, _("Upgrade failed (no plasma ammo)")); } break; @@ -421,11 +428,11 @@ static void game_doCollectables() game.maxPlasmaDamage, weapons[W_PLAYER_WEAPON].damage + 1); if (weapons[W_PLAYER_WEAPON].damage >= game.maxPlasmaDamage) - strcpy(temp, "Plasma damage already at maximum"); + strcpy(temp, _("Plasma damage already at maximum")); else { weapons[W_PLAYER_WEAPON].damage++; - strcpy(temp, "Plasma damage increased"); + strcpy(temp, _("Plasma damage increased")); } } else if ((game.area != MISN_INTERCEPTION) || @@ -436,16 +443,16 @@ static void game_doCollectables() 0, game.maxPlasmaAmmo); if (weapons[W_PLAYER_WEAPON].damage >= game.maxPlasmaDamage) - strcpy(temp, "Plasma damage already at maximum"); + strcpy(temp, _("Plasma damage already at maximum")); else { weapons[W_PLAYER_WEAPON].damage++; - strcpy(temp, "Plasma damage increased"); + strcpy(temp, _("Plasma damage increased")); } } else { - strcpy(temp, "Upgrade failed (no plasma ammo)"); + strcpy(temp, _("Upgrade failed (no plasma ammo)")); } break; @@ -466,51 +473,54 @@ static void game_doCollectables() weapons[W_PLAYER_WEAPON].reload[0] = rate2reload[5]; weapons[W_PLAYER_WEAPON].flags |= WF_SPREAD; - strcpy(temp, "Picked up a Super Charge!"); + strcpy(temp, _("Picked up a Super Charge!")); } else { - strcpy(temp, "Damn! Upgrade failed (no plasma ammo)"); + /// Rare case of grabbing the super charge when you have no ammo at an + /// interception (which means it won't take effect). The "Damn!" serves + /// as a little sympathetic easter egg for players unfortunate enough to + /// have this happen to them. + strcpy(temp, _("Damn! Upgrade failed (no plasma ammo)")); } break; case P_PLASMA_AMMO: if (player.ammo[0] >= game.maxPlasmaAmmo) - strcpy(temp, "Plasma cells already at Maximum"); + strcpy(temp, _("Plasma cells already at Maximum")); else { LIMIT_ADD(player.ammo[0], collectable->value, 0, game.maxPlasmaAmmo); - if (collectable->value > 1) - { - snprintf(temp, STRMAX_SHORT, "Got %d plasma cells", collectable->value); - } - else - { - strcpy(temp, "Got a plasma cell"); - if ((rand() % 25) == 0) - strcpy(temp, "Got one whole plasma cell (wahoo!)"); - } + snprintf(temp, STRMAX_SHORT, ngettext( + /// "%d" must be retained. It is replaced with the number of plasma + /// cells picked up. + "Got %d plasma cell", + "Got %d plasma cells", + collectable->value), collectable->value); } game.cellPickups += collectable->value; break; case P_CARGO: - strcpy(temp, "Picked up some Cargo"); + strcpy(temp, _("Picked up some Cargo")); game.cargoPickups++; break; case P_SLAVES: - snprintf(temp, STRMAX_SHORT, "Rescued %d slaves", collectable->value); + snprintf(temp, STRMAX_SHORT, ngettext( + "Rescued %d slave", + "Rescued %d slaves", + collectable->value), collectable->value); game.slavesRescued += collectable->value; break; case P_ESCAPEPOD: - strcpy(temp, "Picked up an Escape Pod"); + strcpy(temp, _("Picked up an Escape Pod")); break; case P_ORE: - strcpy(temp, "Picked up some Ore"); + strcpy(temp, _("Picked up some Ore")); break; } diff --git a/src/gfx.c b/src/gfx.c index fbab81d..e69a8b0 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -159,10 +159,11 @@ void gfx_blit(SDL_Surface *image, int x, int y, SDL_Surface *dest) In 16 bit mode this is slow. VERY slow. Don't write directly to a surface that constantly needs updating (eg - the main game screen) */ -static int gfx_renderStringBase(const char *in, int x, int y, int fontColor, int wrap, SDL_Surface *dest) +static int gfx_renderStringBase(const char *in, int x, int y, int real_x, int fontColor, int wrap, SDL_Surface *dest) { int i; int splitword; + int creal_x; SDL_Rect area; SDL_Rect letter; @@ -170,6 +171,7 @@ static int gfx_renderStringBase(const char *in, int x, int y, int fontColor, int area.y = y; area.w = PIXFONT_W; area.h = PIXFONT_H; + creal_x = real_x; letter.y = 0; letter.w = PIXFONT_W; @@ -191,15 +193,17 @@ static int gfx_renderStringBase(const char *in, int x, int y, int fontColor, int } area.x += PIXFONT_W + 1; + creal_x += PIXFONT_W + 1; if (wrap) { - if ((area.x > (dest->w - 70)) && (*in == ' ')) + if ((creal_x > (dest->w - 70)) && (*in == ' ')) { area.y += PIXFONT_LINE_HEIGHT; area.x = x; + creal_x = real_x; } - else if (area.x > (dest->w - 31)) + else if (creal_x > (dest->w - 31)) { splitword = 1; for (i = 0 ; i < 4 ; i++) @@ -222,6 +226,7 @@ static int gfx_renderStringBase(const char *in, int x, int y, int fontColor, int } area.y += PIXFONT_LINE_HEIGHT; area.x = x; + creal_x = real_x; } } } @@ -232,18 +237,27 @@ static int gfx_renderStringBase(const char *in, int x, int y, int fontColor, int return area.y; } +/* +Legacy text rendering function, the original one which only supports +ASCII. Generally not used anymore with the exception of some title +screen bits that remain untranslated, but also used as a fallback if the +game is compiled without SDL_ttf and Pango. Works OK on the English +text, but not likely to work well with translations (and won't work at +all for languages like Chinese or Japanese based on non-Latin +alphabets). +*/ int gfx_renderString(const char *in, int x, int y, int fontColor, int wrap, SDL_Surface *dest) { if (x == -1) x = (dest->w - (strlen(in) * (PIXFONT_W + 1))) / 2; - gfx_renderStringBase(in, x, y - 1, FONT_OUTLINE, wrap, dest); - gfx_renderStringBase(in, x, y + 1, FONT_OUTLINE, wrap, dest); - gfx_renderStringBase(in, x, y + 2, FONT_OUTLINE, wrap, dest); - gfx_renderStringBase(in, x - 1, y, FONT_OUTLINE, wrap, dest); - gfx_renderStringBase(in, x - 2, y, FONT_OUTLINE, wrap, dest); - gfx_renderStringBase(in, x + 1, y, FONT_OUTLINE, wrap, dest); - return gfx_renderStringBase(in, x, y, fontColor, wrap, dest); + gfx_renderStringBase(in, x, y - 1, x, FONT_OUTLINE, wrap, dest); + gfx_renderStringBase(in, x, y + 1, x, FONT_OUTLINE, wrap, dest); + gfx_renderStringBase(in, x, y + 2, x, FONT_OUTLINE, wrap, dest); + gfx_renderStringBase(in, x - 1, y, x, FONT_OUTLINE, wrap, dest); + gfx_renderStringBase(in, x - 2, y, x, FONT_OUTLINE, wrap, dest); + gfx_renderStringBase(in, x + 1, y, x, FONT_OUTLINE, wrap, dest); + return gfx_renderStringBase(in, x, y, x, fontColor, wrap, dest); } #ifdef NOFONT diff --git a/src/intermission.c b/src/intermission.c index 7040c76..b6bafe0 100644 --- a/src/intermission.c +++ b/src/intermission.c @@ -1639,7 +1639,7 @@ int intermission() { /// Retain "%s" as-is. It is replaced with the name of the planet /// the player's destination is currently set to. - snprintf(string, STRMAX_SHORT, "Destination: %s", intermission_planets[game.destinationPlanet].name); + snprintf(string, STRMAX_SHORT, _("Destination: %s"), intermission_planets[game.destinationPlanet].name); gfx_createTextObject(TS_DEST_PLANET, string, 0, 0, FONT_WHITE); } diff --git a/src/mission.c b/src/mission.c index 9b2041e..93bbd3d 100644 --- a/src/mission.c +++ b/src/mission.c @@ -673,7 +673,7 @@ static void mission_evaluate(int type, int id, int *completed, int *targetValue, snprintf(message, STRMAX_SHORT, fmt, *targetValue); break; case P_ORE: - radio_getRandomMessage(fmt,ngettext( + radio_getRandomMessage(fmt, ngettext( /// Info line messages for remaining ore to collect /// This is a "\n"-separated list of possible choices to make. Please feel free /// to add as many as you like. Each entry must have one instance of "%d", which