4 * Copyright (C) 1993-1999 by Jochen Wiedmann and Marcin Orlowski
5 * Copyright (C) 2002-2015 FlexCat Open Source Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "showfuncs.h"
26 #include "readprefs.h"
27 #include "swapfuncs.h"
31 struct CatString
*FirstCatString
= NULL
; /* First catalog string */
32 struct CatalogChunk
*FirstChunk
= NULL
; /* List of catalog chunks */
36 /* CatPuts prints a string to a catalog. (The string is preceded by a
37 long integer containing its length and probably padded up to word
38 boundary or longword boundary, depending on the argument padbytes.)
39 The arguments countnul should be TRUE if the NUL byte at the end of
40 the string should be counted. */
42 int CatPuts(FILE *fp
, char *str
, int padbytes
, int countnul
, int lenbytes
)
52 /* Get length of string */
57 while(*oldstr
!= '\0')
59 bytesread
= ReadChar(&oldstr
, bytes
);
60 // substract one byte for double backslashes
67 virtuallen
= chunklen
= reallen
+ lenbytes
;
68 if(countnul
|| chunklen
% padbytes
== 0)
71 swapped_long
= SwapLong(virtuallen
);
73 fwrite(&swapped_long
, sizeof(virtuallen
), 1, fp
);
75 fwrite(((char *)&reallen
) + sizeof(reallen
) - lenbytes
, lenbytes
, 1, fp
);
79 bytesread
= ReadChar(&str
, bytes
);
81 fwrite(bytes
+ bytesread
- 1, 1, 1, fp
);
88 while(++chunklen
% padbytes
);
90 return (int)chunklen
+ 4;
96 /* This puts a string chunk into the catalog */
98 int PutCatalogChunk(FILE * fp
, struct CatalogChunk
*cc
)
100 fwrite(&cc
->ID
, sizeof(cc
->ID
), 1, fp
);
102 return 4 + CatPuts(fp
, cc
->ChunkStr
, 2, TRUE
, 0);
108 /* This creates a catalog */
110 void CreateCat(char *CatFile
)
114 struct CatString
*cs
;
115 struct CatalogChunk
*cc
;
118 if(CatVersionString
== NULL
&& CatRcsId
== NULL
)
120 ShowError(MSG_ERR_NOCTVERSION
);
123 if(CatLanguage
== NULL
)
125 ShowError(MSG_ERR_NOCTLANGUAGE
);
128 if(strlen(CatLanguage
) == 0)
130 ShowError(MSG_ERR_NOCTLANGUAGE
);
136 ShowError(MSG_ERR_NOCATFILENAME
);
139 if(asprintf(&CatFile
, "%s.catalog", BaseName
) < 0)
144 if((fp
= fopen(CatFile
, "wb")) == NULL
)
146 ShowError(MSG_ERR_NOCATALOG
, CatFile
);
150 setvbuf(fp
, NULL
, _IOFBF
, buffer_size
);
152 fputs("FORM0000CTLG", fp
);
155 if(CatVersionString
!=NULL
)
157 struct CatalogChunk verChunk
;
160 verChunk
.ID
= MAKE_ID('F', 'V', 'E', 'R');
162 verChunk
.ChunkStr
= strdup(CatVersionString
);
164 /* Replace $TODAY placeholder */
166 found
= strstr(verChunk
.ChunkStr
, "$TODAY");
178 strftime(dateStr
, sizeof(dateStr
), "%d.%m.%Y", t
);
180 if(asprintf(&verStr
, "%s%s%s", verChunk
.ChunkStr
, dateStr
, found
+ strlen("$TODAY")) != -1)
182 free(verChunk
.ChunkStr
);
183 verChunk
.ChunkStr
= verStr
;
189 /* Replace ".ct" with ".catalog" */
191 found
= strstr(verChunk
.ChunkStr
, ".ct ");
197 if(asprintf(&verStr
, "%s.catalog%s", verChunk
.ChunkStr
, found
+ 3) != -1)
199 free(verChunk
.ChunkStr
);
200 verChunk
.ChunkStr
= verStr
;
204 verChunk
.ID
= SwapLong(verChunk
.ID
);
205 CatLen
+= PutCatalogChunk(fp
, &verChunk
);
206 free(verChunk
.ChunkStr
);
210 struct CatalogChunk verChunk
;
212 int year
= 0, month
= 0, day
= 0;
213 int version
= 0, revision
= 0;
219 ShowError(MSG_ERR_NOCTVERSION
);
223 if((ptr
= strstr(CatRcsId
, "$Date:")) == NULL
||
224 sscanf(ptr
+ 6, " %d/%d/%d", &year
, &month
, &day
) != 3 ||
225 (ptr
= strstr(CatRcsId
, "$Revision:")) == NULL
||
226 sscanf(ptr
+ 10, " %d.%d", &version
, &revision
) != 2)
228 ShowError(MSG_ERR_WRONGRCSID
);
230 if((ptr
= strstr(CatRcsId
, "$Id:")) != NULL
)
239 while(*ptr
!= '\0' && *ptr
!= '$' && *ptr
!= ' ' && *ptr
!= '\t')
244 if((name
= malloc(len
+ 1)) == NULL
)
248 strncpy(name
, found
, len
);
257 else if(name
== NULL
)
259 ShowError(MSG_ERR_NOCTVERSION
);
263 if(asprintf(&verStr
, "%cVER: %s %d.%d (%d.%d.%d)", '$', name
, version
, revision
, day
, month
, year
) != -1)
265 verChunk
.ID
= MAKE_ID('F', 'V', 'E', 'R');
266 verChunk
.ID
= SwapLong(verChunk
.ID
);
267 verChunk
.ChunkStr
= verStr
;
268 CatLen
+= PutCatalogChunk(fp
, &verChunk
);
274 for(cc
= FirstChunk
; cc
!= NULL
; cc
= cc
->Next
)
276 CatLen
+= PutCatalogChunk(fp
, cc
);
283 int i_tmp
= SwapLong(i
);
285 fwrite(&i_tmp
, sizeof(i_tmp
), 1, fp
);
286 i_tmp
= SwapLong(CodeSet
);
287 fwrite(&i_tmp
, sizeof(i_tmp
), 1, fp
);
297 fprintf(fp
, "STRS0000");
300 for(cs
= FirstCatString
; cs
!= NULL
; cs
= cs
->Next
)
302 int FillUsed
= FALSE
;
303 int tmp_ID
= SwapLong(cs
->ID
);
307 if(cs
->CT_Str
!= NULL
&& cs
->NotInCT
== FALSE
)
309 if(strlen(cs
->CT_Str
) == 0)
311 fwrite(&tmp_ID
, sizeof(tmp_ID
), 1, fp
);
312 CatLen
+= 4 + CatPuts(fp
, cs
->CD_Str
, 4, FALSE
, cs
->LenBytes
);
318 fwrite(&tmp_ID
, sizeof(cs
->ID
), 1, fp
);
319 CatLen
+= 4 + CatPuts(fp
, cs
->CD_Str
, 4, FALSE
, cs
->LenBytes
);
324 if(FillUsed
== FALSE
&& cs
->CT_Str
!= NULL
&& cs
->NotInCT
== FALSE
&&
325 (NoOptim
? TRUE
: strcmp(cs
->CT_Str
, cs
->CD_Str
)))
327 fwrite(&tmp_ID
, sizeof(tmp_ID
), 1, fp
);
328 CatLen
+= 4 + CatPuts(fp
, cs
->CT_Str
, 4, FALSE
, cs
->LenBytes
);
331 /* printf("LB=%d\n", cs->LenBytes); */
337 fseek(fp
, 4, SEEK_SET
);
339 tmp_Len
= SwapLong(CatLen
);
340 fwrite(&tmp_Len
, sizeof(tmp_Len
), 1, fp
);
341 fseek(fp
, HeadLen
- 4, SEEK_CUR
);
344 tmp_Len
= SwapLong(CatLen
);
345 fwrite(&tmp_Len
, sizeof(CatLen
), 1, fp
);
350 SetProtection(CatFile
, FILE_MASK
);