URI: 
       ttstring.c - vaccinewars - be a doctor and try to vaccinate the world
  HTML git clone git://src.adamsgaard.dk/vaccinewars
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       ttstring.c (8237B)
       ---
            1 /************************************************************************
            2  * tstring.c      "Translated string" wrappers for dopewars             *
            3  * Copyright (C)  1998-2021  Ben Webb                                   *
            4  *                Email: benwebb@users.sf.net                           *
            5  *                WWW: https://dopewars.sourceforge.io/                 *
            6  *                                                                      *
            7  * This program is free software; you can redistribute it and/or        *
            8  * modify it under the terms of the GNU General Public License          *
            9  * as published by the Free Software Foundation; either version 2       *
           10  * of the License, or (at your option) any later version.               *
           11  *                                                                      *
           12  * This program is distributed in the hope that it will be useful,      *
           13  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
           14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
           15  * GNU General Public License for more details.                         *
           16  *                                                                      *
           17  * You should have received a copy of the GNU General Public License    *
           18  * along with this program; if not, write to the Free Software          *
           19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,               *
           20  *                   MA  02111-1307, USA.                               *
           21  ************************************************************************/
           22 
           23 #include <stdio.h>
           24 #include <string.h>
           25 #include <stdarg.h>
           26 
           27 #ifdef HAVE_CONFIG_H
           28 #include <config.h>
           29 #endif
           30 
           31 #include <glib.h>
           32 #include "dopewars.h"
           33 #include "message.h"
           34 #include "tstring.h"
           35 
           36 typedef struct _FmtData {
           37   union {
           38     int IntVal;
           39     price_t PriceVal;
           40     char CharVal;
           41     char *StrVal;
           42   } data;
           43   char Type;
           44 } FmtData;
           45 
           46 gchar *GetDefaultTString(gchar *tstring)
           47 {
           48   gchar *dstr, *pt;
           49 
           50   dstr = g_strdup(tstring);
           51   pt = strchr(dstr, '_');
           52   if (pt)
           53     *pt = '\0';
           54   return dstr;
           55 }
           56 
           57 gchar *GetTranslatedString(gchar *str, gchar *code, gboolean Caps)
           58 {
           59   gchar *dstr, *pt, *tstr, *Default, *tcode;
           60 
           61   dstr = g_strdup(str);
           62   g_strdelimit(dstr, "_", '^');
           63   pt = dstr;
           64   Default = GetNextWord(&pt, "");
           65   tstr = NULL;
           66 
           67   while (1) {
           68     tcode = GetNextWord(&pt, NULL);
           69     tstr = GetNextWord(&pt, "");
           70     if (!tcode) {
           71       tstr = NULL;
           72       break;
           73     }
           74     if (strcmp(tcode, code) == 0) {
           75       break;
           76     } else
           77       tstr = NULL;
           78   }
           79 
           80   if (tstr) {
           81     if (Caps)
           82       tstr = InitialCaps(tstr);
           83     else
           84       tstr = g_strdup(tstr);
           85   } else {
           86     if (Caps)
           87       tstr = InitialCaps(Default);
           88     else
           89       tstr = g_strdup(Default);
           90   }
           91 
           92   g_free(dstr);
           93   return tstr;
           94 }
           95 
           96 void GetNextFormat(guint *Index, gchar *str, int *StartPos,
           97                    int *EndPos, int *FmtPos, gchar *Type, int *ArgNum,
           98                    int *Wid, int *Prec, char *Code)
           99 {
          100   int anum, wid, prec;
          101   guint i;
          102   gchar type;
          103 
          104   *StartPos = -1;
          105   *EndPos = *FmtPos = *ArgNum = *Wid = *Prec = 0;
          106   *Type = 0;
          107   Code[0] = 0;
          108   anum = wid = prec = 0;
          109   i = *Index;
          110   while (str[i]) {
          111     if (str[i] == '%') {
          112       *StartPos = *EndPos = i++;
          113       while (strchr("#0- +'", str[i]))
          114         i++;                    /* Skip flag characters */
          115       while (str[i] >= '0' && str[i] <= '9')
          116         wid = wid * 10 + str[i++] - '0';
          117       if (str[i] == '$') {
          118         *EndPos = i;
          119         i++;
          120         anum = wid;
          121         wid = 0;
          122         while (strchr("#0- +'", str[i]))
          123           i++;                  /* Skip flag characters */
          124         while (str[i] >= '0' && str[i] <= '9')
          125           wid = wid * 10 + str[i++] - '0';
          126       }
          127       if (str[i] == '.') {
          128         i++;
          129         while (str[i] >= '0' && str[i] <= '9')
          130           prec = prec * 10 + str[i++] - '0';
          131       }
          132       *FmtPos = i;
          133       type = str[i];
          134       if ((type == 'T' || type == 't') && i + 2 < strlen(str)) {
          135         Code[0] = str[i + 1];
          136         Code[1] = str[i + 2];
          137         Code[2] = 0;
          138         i += 3;
          139       } else if (type == '/') {
          140         i++;
          141         while (str[i] != '\0' && str[i] != '/')
          142           i++;
          143         if (str[i] == '/')
          144           i++;
          145       } else
          146         i++;
          147       *ArgNum = anum;
          148       *Wid = wid;
          149       *Prec = prec;
          150       *Index = i;
          151       *Type = type;
          152       return;
          153     } else
          154       i++;
          155   }
          156   *Index = i;
          157 }
          158 
          159 gchar *HandleTFmt(gchar *format, va_list va)
          160 {
          161   int StrInd, StartPos, EndPos, FmtPos, Wid, Prec, ArgNum, DefaultArgNum;
          162   guint i;
          163   char Code[3], Type;
          164   gchar *retstr, *fstr;
          165   GString *string, *tmpfmt;
          166   GArray *arr;
          167   FmtData *fdat;
          168 
          169   string = g_string_new("");
          170   tmpfmt = g_string_new("");
          171 
          172   arr = g_array_new(FALSE, TRUE, sizeof(FmtData));
          173   i = DefaultArgNum = 0;
          174   while (i < strlen(format)) {
          175     GetNextFormat(&i, format, &StartPos, &EndPos, &FmtPos, &Type, &ArgNum,
          176                   &Wid, &Prec, Code);
          177     if (StartPos == -1)
          178       break;
          179     if (ArgNum == 0)
          180       ArgNum = ++DefaultArgNum;
          181     if (ArgNum > arr->len) {
          182       g_array_set_size(arr, ArgNum);
          183     }
          184     g_array_index(arr, FmtData, ArgNum - 1).Type = Type;
          185   }
          186   for (i = 0; i < arr->len; i++) {
          187     fdat = &g_array_index(arr, FmtData, i);
          188 
          189     switch (fdat->Type) {
          190     case '\0':
          191       g_error("Incomplete format string!");
          192       break;
          193     case 'd':
          194       fdat->data.IntVal = va_arg(va, int);
          195       break;
          196     case 'P':
          197       fdat->data.PriceVal = va_arg(va, price_t);
          198       break;
          199     case 'c':
          200       fdat->data.CharVal = (char)va_arg(va, int);
          201       break;
          202     case 's':
          203     case 't':
          204     case 'T':
          205       fdat->data.StrVal = va_arg(va, char *);
          206       break;
          207     case '%':
          208     case '/':
          209       break;                    /* No special action for %% or %/.../ */
          210     default:
          211       g_error("Unknown format type %c!", fdat->Type);
          212     }
          213   }
          214   i = DefaultArgNum = 0;
          215   while (i < strlen(format)) {
          216     StrInd = i;
          217     GetNextFormat(&i, format, &StartPos, &EndPos, &FmtPos, &Type, &ArgNum,
          218                   &Wid, &Prec, Code);
          219     if (StartPos == -1) {
          220       g_string_append(string, &format[StrInd]);
          221       break;
          222     }
          223     while (StrInd < StartPos)
          224       g_string_append_c(string, format[StrInd++]);
          225     if (ArgNum == 0)
          226       ArgNum = ++DefaultArgNum;
          227     g_string_assign(tmpfmt, "%");
          228     EndPos++;
          229     while (EndPos < FmtPos)
          230       g_string_append_c(tmpfmt, format[EndPos++]);
          231     if (Type == 'T' || Type == 't' || Type == 'P')
          232       g_string_append_c(tmpfmt, 's');
          233     else
          234       g_string_append_c(tmpfmt, Type);
          235     fdat = &g_array_index(arr, FmtData, ArgNum - 1);
          236 
          237     if (Type != fdat->Type)
          238       g_error("Unmatched types!");
          239     switch (Type) {
          240     case 'd':
          241       g_string_append_printf(string, tmpfmt->str, fdat->data.IntVal);
          242       break;
          243     case 'c':
          244       g_string_append_printf(string, tmpfmt->str, fdat->data.CharVal);
          245       break;
          246     case 'P':
          247       fstr = FormatPrice(fdat->data.PriceVal);
          248       g_string_append_printf(string, tmpfmt->str, fstr);
          249       g_free(fstr);
          250       break;
          251     case 't':
          252     case 'T':
          253       fstr = GetTranslatedString(fdat->data.StrVal, Code, Type == 'T');
          254       g_string_append_printf(string, tmpfmt->str, fstr);
          255       g_free(fstr);
          256       break;
          257     case 's':
          258       g_string_append_printf(string, tmpfmt->str, fdat->data.StrVal);
          259       break;
          260     case '%':
          261       g_string_append_c(string, '%');
          262       break;
          263     }
          264   }
          265   retstr = string->str;
          266   g_array_free(arr, TRUE);
          267   g_string_free(string, FALSE);
          268   g_string_free(tmpfmt, TRUE);
          269   return retstr;
          270 }
          271 
          272 void dpg_print(gchar *format, ...)
          273 {
          274   va_list ap;
          275   gchar *retstr;
          276 
          277   va_start(ap, format);
          278   retstr = HandleTFmt(format, ap);
          279   va_end(ap);
          280   g_print("%s", retstr);
          281   g_free(retstr);
          282 }
          283 
          284 gchar *dpg_strdup_printf(gchar *format, ...)
          285 {
          286   va_list ap;
          287   gchar *retstr;
          288 
          289   va_start(ap, format);
          290   retstr = HandleTFmt(format, ap);
          291   va_end(ap);
          292   return retstr;
          293 }
          294 
          295 void dpg_string_printf(GString *string, gchar *format, ...)
          296 {
          297   va_list ap;
          298   gchar *newstr;
          299 
          300   va_start(ap, format);
          301   newstr = HandleTFmt(format, ap);
          302   g_string_assign(string, newstr);
          303   g_free(newstr);
          304   va_end(ap);
          305 }
          306 
          307 void dpg_string_append_printf(GString *string, gchar *format, ...)
          308 {
          309   va_list ap;
          310   gchar *newstr;
          311 
          312   va_start(ap, format);
          313   newstr = HandleTFmt(format, ap);
          314   g_string_append(string, newstr);
          315   g_free(newstr);
          316   va_end(ap);
          317 }