| ---
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
24 #include
25 #include
26
27 #ifdef HAVE_CONFIG_H
28 #include
29 #endif
30
31 #include
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 } |