1 /*	Public domain	*/
2 
3 #ifndef _AGAR_CORE_TEXT_H_
4 #define _AGAR_CORE_TEXT_H_
5 #include <agar/core/begin.h>
6 
7 /* Language code (see iso639-gen.pl) */
8 enum ag_language {
9 	AG_LANG_NONE,	/* Undefined */
10 	AG_LANG_AA,	/* Afar */
11 	AG_LANG_AB,	/* Abkhazian */
12 	AG_LANG_AF,	/* Afrikaans */
13 	AG_LANG_AM,	/* Amharic */
14 	AG_LANG_AR,	/* Arabic */
15 	AG_LANG_AS,	/* Assamese */
16 	AG_LANG_AY,	/* Aymara */
17 	AG_LANG_AZ,	/* Azerbaijani */
18 	AG_LANG_BA,	/* Bashkir */
19 	AG_LANG_BE,	/* Byelorussian */
20 	AG_LANG_BG,	/* Bulgarian */
21 	AG_LANG_BH,	/* Bihari */
22 	AG_LANG_BI,	/* Bislama */
23 	AG_LANG_BN,	/* Bengali; Bangla */
24 	AG_LANG_BO,	/* Tibetan */
25 	AG_LANG_BR,	/* Breton */
26 	AG_LANG_CA,	/* Catalan */
27 	AG_LANG_CO,	/* Corsican */
28 	AG_LANG_CS,	/* Czech */
29 	AG_LANG_CY,	/* Welsh */
30 	AG_LANG_DA,	/* Danish */
31 	AG_LANG_DE,	/* German */
32 	AG_LANG_DZ,	/* Bhutani */
33 	AG_LANG_EL,	/* Greek */
34 	AG_LANG_EN,	/* English */
35 	AG_LANG_EO,	/* Esperanto */
36 	AG_LANG_ES,	/* Spanish */
37 	AG_LANG_ET,	/* Estonian */
38 	AG_LANG_EU,	/* Basque */
39 	AG_LANG_FA,	/* Persian */
40 	AG_LANG_FI,	/* Finnish */
41 	AG_LANG_FJ,	/* Fiji */
42 	AG_LANG_FO,	/* Faroese */
43 	AG_LANG_FR,	/* French */
44 	AG_LANG_FY,	/* Frisian */
45 	AG_LANG_GA,	/* Irish */
46 	AG_LANG_GD,	/* Scots Gaelic */
47 	AG_LANG_GL,	/* Galician */
48 	AG_LANG_GN,	/* Guarani */
49 	AG_LANG_GU,	/* Gujarati */
50 	AG_LANG_HA,	/* Hausa */
51 	AG_LANG_HE,	/* Hebrew (formerly iw) */
52 	AG_LANG_HI,	/* Hindi */
53 	AG_LANG_HR,	/* Croatian */
54 	AG_LANG_HU,	/* Hungarian */
55 	AG_LANG_HY,	/* Armenian */
56 	AG_LANG_IA,	/* Interlingua */
57 	AG_LANG_ID,	/* Indonesian (formerly in) */
58 	AG_LANG_IE,	/* Interlingue */
59 	AG_LANG_IK,	/* Inupiak */
60 	AG_LANG_IS,	/* Icelandic */
61 	AG_LANG_IT,	/* Italian */
62 	AG_LANG_IU,	/* Inuktitut */
63 	AG_LANG_JA,	/* Japanese */
64 	AG_LANG_JW,	/* Javanese */
65 	AG_LANG_KA,	/* Georgian */
66 	AG_LANG_KK,	/* Kazakh */
67 	AG_LANG_KL,	/* Greenlandic */
68 	AG_LANG_KM,	/* Cambodian */
69 	AG_LANG_KN,	/* Kannada */
70 	AG_LANG_KO,	/* Korean */
71 	AG_LANG_KS,	/* Kashmiri */
72 	AG_LANG_KU,	/* Kurdish */
73 	AG_LANG_KY,	/* Kirghiz */
74 	AG_LANG_LA,	/* Latin */
75 	AG_LANG_LN,	/* Lingala */
76 	AG_LANG_LO,	/* Laothian */
77 	AG_LANG_LT,	/* Lithuanian */
78 	AG_LANG_LV,	/* Latvian, Lettish */
79 	AG_LANG_MG,	/* Malagasy */
80 	AG_LANG_MI,	/* Maori */
81 	AG_LANG_MK,	/* Macedonian */
82 	AG_LANG_ML,	/* Malayalam */
83 	AG_LANG_MN,	/* Mongolian */
84 	AG_LANG_MO,	/* Moldavian */
85 	AG_LANG_MR,	/* Marathi */
86 	AG_LANG_MS,	/* Malay */
87 	AG_LANG_MT,	/* Maltese */
88 	AG_LANG_MY,	/* Burmese */
89 	AG_LANG_NA,	/* Nauru */
90 	AG_LANG_NE,	/* Nepali */
91 	AG_LANG_NL,	/* Dutch */
92 	AG_LANG_NO,	/* Norwegian */
93 	AG_LANG_OC,	/* Occitan */
94 	AG_LANG_OM,	/* (Afan) Oromo */
95 	AG_LANG_OR,	/* Oriya */
96 	AG_LANG_PA,	/* Punjabi */
97 	AG_LANG_PL,	/* Polish */
98 	AG_LANG_PS,	/* Pashto, Pushto */
99 	AG_LANG_PT,	/* Portuguese */
100 	AG_LANG_QU,	/* Quechua */
101 	AG_LANG_RM,	/* Rhaeto-Romance */
102 	AG_LANG_RN,	/* Kirundi */
103 	AG_LANG_RO,	/* Romanian */
104 	AG_LANG_RU,	/* Russian */
105 	AG_LANG_RW,	/* Kinyarwanda */
106 	AG_LANG_SA,	/* Sanskrit */
107 	AG_LANG_SD,	/* Sindhi */
108 	AG_LANG_SG,	/* Sangho */
109 	AG_LANG_SH,	/* Serbo-Croatian */
110 	AG_LANG_SI,	/* Sinhalese */
111 	AG_LANG_SK,	/* Slovak */
112 	AG_LANG_SL,	/* Slovenian */
113 	AG_LANG_SM,	/* Samoan */
114 	AG_LANG_SN,	/* Shona */
115 	AG_LANG_SO,	/* Somali */
116 	AG_LANG_SQ,	/* Albanian */
117 	AG_LANG_SR,	/* Serbian */
118 	AG_LANG_SS,	/* Siswati */
119 	AG_LANG_ST,	/* Sesotho */
120 	AG_LANG_SU,	/* Sundanese */
121 	AG_LANG_SV,	/* Swedish */
122 	AG_LANG_SW,	/* Swahili */
123 	AG_LANG_TA,	/* Tamil */
124 	AG_LANG_TE,	/* Telugu */
125 	AG_LANG_TG,	/* Tajik */
126 	AG_LANG_TH,	/* Thai */
127 	AG_LANG_TI,	/* Tigrinya */
128 	AG_LANG_TK,	/* Turkmen */
129 	AG_LANG_TL,	/* Tagalog */
130 	AG_LANG_TN,	/* Setswana */
131 	AG_LANG_TO,	/* Tonga */
132 	AG_LANG_TR,	/* Turkish */
133 	AG_LANG_TS,	/* Tsonga */
134 	AG_LANG_TT,	/* Tatar */
135 	AG_LANG_TW,	/* Twi */
136 	AG_LANG_UG,	/* Uighur */
137 	AG_LANG_UK,	/* Ukrainian */
138 	AG_LANG_UR,	/* Urdu */
139 	AG_LANG_UZ,	/* Uzbek */
140 	AG_LANG_VI,	/* Vietnamese */
141 	AG_LANG_VO,	/* Volapuk */
142 	AG_LANG_WO,	/* Wolof */
143 	AG_LANG_XH,	/* Xhosa */
144 	AG_LANG_YI,	/* Yiddish (formerly ji) */
145 	AG_LANG_YO,	/* Yoruba */
146 	AG_LANG_ZA,	/* Zhuang */
147 	AG_LANG_ZH,	/* Chinese */
148 	AG_LANG_ZU,	/* Zulu */
149 	AG_LANG_LAST
150 };
151 
152 /* Text entry */
153 typedef struct ag_text_ent {
154 	char  *buf;			/* String buffer */
155 	size_t maxLen;			/* Length (allocated) */
156 	size_t len;			/* Length (chars) */
157 } AG_TextEnt;
158 
159 /* Text object */
160 typedef struct ag_text {
161 	AG_Mutex lock;
162 	AG_TextEnt ent[AG_LANG_LAST];	/* Language entries */
163 	enum ag_language lang;		/* Selected language */
164 	size_t maxLen;			/* Maximum string length (bytes) */
165 	Uint flags;
166 #define AG_TEXT_SAVED_FLAGS	0
167 } AG_Text, AG_TextElement;
168 
169 #define AGTEXT(p) ((AG_Text *)(p))
170 
171 __BEGIN_DECLS
172 extern const char *agLanguageCodes[];
173 extern const char *agLanguageNames[];
174 
175 AG_Text    *AG_TextNew(size_t);
176 
177 void        AG_TextInit(AG_Text *, size_t);
178 void        AG_TextDestroy(AG_Text *);
179 
180 void        AG_TextClear(AG_Text *);
181 int         AG_TextSet(AG_Text *, const char *, ...)
182                        FORMAT_ATTRIBUTE(__printf__, 2, 3);
183 int         AG_TextSetEnt(AG_Text *, enum ag_language, const char *, ...)
184                           FORMAT_ATTRIBUTE(__printf__, 3, 4);
185 int         AG_TextSetEntS(AG_Text *, enum ag_language, const char *);
186 
187 int         AG_TextSetLangISO(AG_Text *, const char *);
188 const char *AG_TextGetLangISO(AG_Text *);
189 AG_Text    *AG_TextDup(AG_Text *);
190 int         AG_TextLoad(AG_Text *, AG_DataSource *);
191 void        AG_TextSave(AG_DataSource *, AG_Text *);
192 
193 /* Set text of current entry from C string */
194 static __inline__ int
AG_TextSetS(AG_Text * txt,const char * s)195 AG_TextSetS(AG_Text *txt, const char *s)
196 {
197 	int rv;
198 	AG_MutexLock(&txt->lock);
199 	rv = AG_TextSetEntS(txt, txt->lang, s);
200 	AG_MutexUnlock(&txt->lock);
201 	return (rv);
202 }
203 
204 /* Set the size limit on strings. */
205 static __inline__ void
AG_TextSetLimit(AG_Text * txt,size_t maxLen)206 AG_TextSetLimit(AG_Text *txt, size_t maxLen)
207 {
208 	AG_MutexLock(&txt->lock);
209 	txt->maxLen = maxLen;
210 	AG_MutexUnlock(&txt->lock);
211 }
212 
213 /* Select the active language. */
214 static __inline__ void
AG_TextSetLang(AG_Text * txt,enum ag_language lang)215 AG_TextSetLang(AG_Text *txt, enum ag_language lang)
216 {
217 	AG_MutexLock(&txt->lock);
218 	txt->lang = lang;
219 	AG_MutexUnlock(&txt->lock);
220 }
221 
222 /* Get the active language. */
223 static __inline__ enum ag_language
AG_TextGetLang(AG_Text * txt)224 AG_TextGetLang(AG_Text *txt)
225 {
226 	enum ag_language lang;
227 	AG_MutexLock(&txt->lock);
228 	lang = txt->lang;
229 	AG_MutexUnlock(&txt->lock);
230 	return (lang);
231 }
232 
233 /* Reallocate entry's buffer to size in bytes. */
234 static __inline__ int
AG_TextRealloc(AG_TextEnt * te,size_t maxLenNew)235 AG_TextRealloc(AG_TextEnt *te, size_t maxLenNew)
236 {
237 	if (maxLenNew >= te->maxLen) {
238 		char *bufNew;
239 		bufNew = (char *)AG_TryRealloc(te->buf, maxLenNew);
240 		if (bufNew == NULL) {
241 			return (-1);
242 		}
243 		te->buf = bufNew;
244 		te->maxLen = maxLenNew;
245 	}
246 	return (0);
247 }
248 
249 /* Append a valid C string to the current buffer. */
250 static __inline__ int
AG_TextCatS(AG_Text * txt,const char * s)251 AG_TextCatS(AG_Text *txt, const char *s)
252 {
253 	AG_TextEnt *te;
254 	size_t len;
255 
256 	len = strlen(s);
257 
258 	AG_MutexLock(&txt->lock);
259 	te = &txt->ent[txt->lang];
260 	if (AG_TextRealloc(te, te->len + len + 1) == -1) {
261 		AG_MutexUnlock(&txt->lock);
262 		return (-1);
263 	}
264 	memcpy(&te->buf[te->len], s, len+1);
265 	te->len += len;
266 	AG_MutexUnlock(&txt->lock);
267 	return (0);
268 }
269 /* Append an arbitrary block of bytes to the current buffer. */
270 static __inline__ int
AS_StringCatBytes(AG_Text * txt,const char * s,size_t len)271 AS_StringCatBytes(AG_Text *txt, const char *s, size_t len)
272 {
273 	AG_TextEnt *te;
274 
275 	AG_MutexLock(&txt->lock);
276 	te = &txt->ent[txt->lang];
277 	if (AG_TextRealloc(te, te->len + len + 1) == -1) {
278 		AG_MutexUnlock(&txt->lock);
279 		return (-1);
280 	}
281 	memcpy(&te->buf[te->len], s, len);
282 	te->len += len;
283 	AG_MutexUnlock(&txt->lock);
284 	return (0);
285 }
286 
287 /* Free an autoallocated AG_Text element. */
288 static __inline__ void
AG_TextFree(AG_Text * txt)289 AG_TextFree(AG_Text *txt)
290 {
291 	if (txt == NULL) {
292 		return;
293 	}
294 	AG_TextDestroy(txt);
295 	AG_Free(txt);
296 }
297 __END_DECLS
298 
299 #include <agar/core/close.h>
300 #endif /* _AGAR_CORE_TEXT_H_ */
301