Merge branch 'master' into gtk3
[projects/chimara/chimara.git] / babel / babel_multi_functions.c
1 #include "babel.h"\r
2 \r
3 #include <stdio.h>\r
4 #include <stdlib.h>\r
5 #include <string.h>\r
6 #include <ctype.h>\r
7 \r
8 #ifdef __cplusplus\r
9 extern "C" {\r
10 #endif\r
11 int chdir(const char *);\r
12 char *getcwd(char *, int);\r
13 #ifdef __cplusplus\r
14 }\r
15 #endif\r
16 \r
17 void deep_ifiction_verify(char *md, int f);\r
18 void * my_malloc(int32, char *);\r
19 char *blorb_chunk_for_name(char *name);\r
20 #ifndef THREE_LETTER_EXTENSIONS\r
21 static char *ext_table[] = { "zcode", ".zblorb",\r
22                              "glulx", ".gblorb",\r
23                              NULL, NULL\r
24                              };\r
25 #else\r
26 static char *ext_table[] = { "zcode", ".zlb",\r
27                              "glulx", ".glb",\r
28                              NULL, NULL\r
29                              };\r
30 \r
31 #endif\r
32 char *blorb_ext_for_name(char *fmt)\r
33 {\r
34  int i;\r
35  for(i=0;ext_table[i];i+=2)\r
36   if (strcmp(ext_table[i],fmt)==0) return ext_table[i+1];\r
37 #ifndef THREE_LETTER_EXTENSIONS\r
38  return ".blorb";\r
39 #else\r
40  return ".blb";\r
41 #endif\r
42 }\r
43 \r
44 char *deep_complete_ifiction(char *fn, char *ifid, char *format)\r
45 {\r
46  FILE *f;\r
47  int32 i;\r
48  char *md;\r
49  char *id, *idp;\r
50  char *idb;\r
51  f=fopen(fn,"r");\r
52  if (!f) { fprintf(stderr,"Error: Can not open file %s\n",fn);\r
53           return NULL;\r
54           }\r
55  fseek(f,0,SEEK_END);\r
56  i=ftell(f);\r
57  fseek(f,0,SEEK_SET);\r
58  md=(char *) my_malloc(i+1,"Metadata buffer");\r
59  fread(md,1,i,f);\r
60  md[i]=0;\r
61  id=strstr(md,"</ifindex>");\r
62  if (id) *(id+10)=0;\r
63  fclose(f);\r
64  id=strdup(ifid);\r
65  idp=strtok(id,",");\r
66  /* Find the identification chunk */\r
67  {\r
68    char *bp, *ep;\r
69    bp=strstr(md,"<identification>");\r
70    if (!bp)\r
71    {\r
72     idb=(char *)my_malloc(TREATY_MINIMUM_EXTENT+128,"ident buffer");\r
73     sprintf(idb,"<format>%s</format>\n", format);\r
74    }\r
75    else\r
76    {\r
77     int ii;\r
78     ep=strstr(bp,"</identification>");\r
79     idb=(char *)my_malloc(TREATY_MINIMUM_EXTENT+128+(ep-bp),"ident buffer");\r
80     for(ii=16;bp+ii<ep;ii++)\r
81     idb[ii-16]=bp[ii];\r
82     idb[ii]=0;\r
83     for(ep+=18;*ep;ep++)\r
84      *bp++=*ep;\r
85     *bp=0;\r
86     bp=strstr(idb,"<format>");\r
87     if (bp)\r
88      if (memcmp(bp+8,format,strlen(format)))\r
89       fprintf(stderr,"Error: Format in sparse .iFiction does not match story\n");\r
90 \r
91    }\r
92 \r
93  }\r
94  /* Insert the new ifids */\r
95  while(idp)\r
96  {\r
97   char bfr[TREATY_MINIMUM_EXTENT];\r
98   sprintf(bfr,"<ifid>%s</ifid>",idp);\r
99   if (!strstr(idb,bfr)) { strcat(idb,bfr); strcat(idb,"\n"); }\r
100   idp=strtok(NULL,",");\r
101 \r
102  }\r
103  free(id);\r
104  idp=(char *) my_malloc(strlen(md)+strlen(idb)+64, "Output metadata");\r
105 /* printf("%d bytes for metadata\n",strlen(md)+strlen(idb)+64);*/\r
106  id=strstr(md,"<story>");\r
107  id[0]=0;\r
108  id+=7;\r
109  strcpy(idp,md);\r
110  strcat(idp,"<story>\n <identification>\n");\r
111  strcat(idp,idb);\r
112  free(idb);\r
113  strcat(idp," </identification>\n");\r
114  strcat(idp,id);\r
115  free(md);\r
116  md=idp;\r
117  deep_ifiction_verify(md, 0);\r
118  return md;\r
119 }\r
120 \r
121 void write_int(int32 i, FILE *f)\r
122 {\r
123  char bf[4];\r
124  bf[0]=(((unsigned) i) >> 24) & 0xFF;\r
125  bf[1]=(((unsigned) i) >> 16) & 0xFF;\r
126  bf[2]=(((unsigned) i) >> 8) & 0xFF;\r
127  bf[3]=(((unsigned) i)) & 0xFF;\r
128  fwrite(bf,1,4,f);\r
129 }\r
130 static void _babel_multi_blorb(char *outfile, char **args, char *todir , int argc)\r
131 {\r
132  int32 total, storyl, coverl, i;\r
133  char buffer[TREATY_MINIMUM_EXTENT+10];\r
134  char b2[TREATY_MINIMUM_EXTENT];\r
135 \r
136  char cwd[512];\r
137  char *cover, *md, *cvrf, *ep;\r
138 \r
139  FILE *f, *c;\r
140  if (argc!=2 && argc !=3)\r
141  {\r
142   fprintf(stderr,"Invalid usage\n");\r
143   return;\r
144  }\r
145  if (!babel_init(args[0]))\r
146  {\r
147   fprintf(stderr,"Error: Could not determine the format of file %s\n",args[0]);\r
148   return;\r
149  }\r
150  if (babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT)<=0 ||\r
151      babel_treaty(GET_FORMAT_NAME_SEL,b2,TREATY_MINIMUM_EXTENT)<0\r
152     )\r
153  {\r
154   fprintf(stderr,"Error: Could not deduce an IFID for file %s\n",args[0]);\r
155   return;\r
156  }\r
157  if (babel_get_length() != babel_get_story_length())\r
158  {\r
159   fprintf(stderr,"Warning: Story file will be extacted from container before blorbing\n");\r
160  }\r
161 /* printf("Completing ifiction\n");*/\r
162  md=deep_complete_ifiction(args[1],buffer,b2);\r
163 /* printf("Ifiction is %d bytes long\n",strlen(md));*/\r
164  ep=strchr(buffer,',');\r
165  if (ep) *ep=0;\r
166  if (outfile)\r
167   strcpy(buffer,outfile);\r
168  strcat(buffer,blorb_ext_for_name(b2));\r
169  getcwd(cwd,512);\r
170  chdir(todir);\r
171  f=fopen(buffer,"wb");\r
172  chdir(cwd);\r
173  if (!f)\r
174  {\r
175   fprintf(stderr,"Error: Error writing to file %s\n",buffer);\r
176   return;\r
177  }\r
178  storyl=babel_get_story_length();\r
179  total=storyl + (storyl%2) + 36;\r
180  if (md) total+=8+strlen(md)+strlen(md)%2;\r
181  if (argc==3)\r
182  {\r
183   c=fopen(args[2],"rb");\r
184   if (c)\r
185   {\r
186    fseek(c,0,SEEK_END);\r
187    coverl=ftell(c);\r
188    if (coverl > 5){\r
189 \r
190    cover=(char *) my_malloc(coverl+2,"Cover art buffer");\r
191    fseek(c,0,SEEK_SET);\r
192    fread(cover,1,coverl,c);\r
193    if (memcmp(cover+1,"PNG",3)==0) cvrf="PNG ";\r
194    else cvrf="JPEG";\r
195    total += 32+coverl + (coverl%2);\r
196    }\r
197    else argc=2;\r
198    fclose(c);\r
199   }\r
200   else argc=2;\r
201  }\r
202 /* printf("Writing header\n;");*/\r
203  fwrite("FORM",1,4,f);\r
204  write_int(total,f);\r
205 /* printf("Writing index\n;");*/\r
206  fwrite("IFRSRIdx",1,8,f);\r
207  write_int(argc==3 ? 28:16,f);\r
208  write_int(argc==3 ? 2:1,f);\r
209 /* printf("Writing story\n;");*/\r
210  fwrite("Exec", 1,4,f);\r
211  write_int(0,f);\r
212  write_int(argc==3 ? 48:36,f);\r
213  if (argc==3)\r
214  {\r
215 /* printf("Writing image\n;"); */\r
216  fwrite("Pict", 1,4,f);\r
217  write_int(1,f);\r
218  write_int(56+storyl+(storyl%2),f);\r
219  }\r
220 /* printf("Invoking chunk for name %s\n",b2); */\r
221  fwrite(blorb_chunk_for_name(b2),1,4,f);\r
222  write_int(storyl,f);\r
223 /* printf("Writing story data\n"); */\r
224  fwrite(babel_get_story_file(),1,storyl,f);\r
225  if (storyl%2) fwrite("\0",1,1,f);\r
226  if (argc==3)\r
227  {\r
228 /*  printf("Writing cover data header %s\n",cvrf); */\r
229   fwrite(cvrf,1,4,f);\r
230 /*  printf("Writing cover data size %d\n",coverl); */\r
231   write_int(coverl,f);\r
232 /*  printf("Writing cover data\n"); */\r
233   fwrite(cover,1,coverl,f);\r
234   if (coverl%2) fwrite("\0",1,1,f);\r
235 /*  printf("Done with cover\n");*/\r
236 /*  free(cover);*/\r
237 /*  printf("Writing frontispiece\n;");*/\r
238   fwrite("Fspc\0\0\0\004\0\0\0\001",1,12,f);\r
239  }\r
240 \r
241  if (md) {\r
242 /*  printf("Writing metadata\n;");*/\r
243  fwrite("IFmd",1,4,f);\r
244  write_int(strlen(md),f);\r
245  fwrite(md,1,strlen(md),f);\r
246  if (strlen(md)%2)\r
247   fwrite("\0",1,1,f);\r
248  free(md);\r
249  }\r
250 \r
251  fclose(f);\r
252  printf("Created %s\n",buffer);\r
253  \r
254 }\r
255 void babel_multi_complete(char **args, char *todir, int argc)\r
256 {\r
257  char buffer[TREATY_MINIMUM_EXTENT+10];\r
258   char b2[TREATY_MINIMUM_EXTENT];\r
259  char cwd[512];\r
260  char *ep, *md;\r
261  FILE *f;\r
262  if (argc!=2)\r
263  {\r
264   fprintf(stderr,"Invalid usage\n");\r
265   return;\r
266  }\r
267  if (!babel_init(args[0]))\r
268  {\r
269   fprintf(stderr,"Error: Could not determine the format of file %s\n",args[0]);\r
270   return;\r
271  }\r
272  if (babel_treaty(GET_STORY_FILE_IFID_SEL,buffer,TREATY_MINIMUM_EXTENT)<=0\r
273     ||  babel_treaty(GET_FORMAT_NAME_SEL,b2,TREATY_MINIMUM_EXTENT)<0)\r
274  {\r
275   fprintf(stderr,"Error: Could not deduce an IFID for file %s\n",args[0]);\r
276   return;\r
277  }\r
278  md=deep_complete_ifiction(args[1],buffer, b2);\r
279  if (!md) return;\r
280  ep=strchr(buffer,',');\r
281  if (ep) *ep=0;\r
282  strcat(buffer,".iFiction");\r
283  getcwd(cwd,512);\r
284  chdir(todir);\r
285  f=fopen(buffer,"w");\r
286  chdir(cwd);\r
287  if (!f || !fputs(md,f))\r
288  {\r
289   fprintf(stderr,"Error: Error writing to file %s\n",buffer);\r
290   return;\r
291  }\r
292  fclose(f);\r
293  free(md);\r
294  printf("Created %s\n",buffer);\r
295 }\r
296 void babel_multi_blorb(char **args, char *todir , int argc)\r
297 {\r
298  _babel_multi_blorb(NULL,args,todir,argc);\r
299 }\r
300 void babel_multi_blorb1(char **args, char *todir , int argc)\r
301 {\r
302  char *buf;\r
303  char *bb;\r
304  buf=(char *)my_malloc(strlen(args[0])+1,"blorb name buffer");\r
305  strcpy(buf,args[0]);\r
306  bb=strrchr(buf,'.');\r
307  if (bb) *bb=0;\r
308  _babel_multi_blorb(buf,args,todir,argc);\r
309  free(buf);\r
310  \r
311 \r
312 }\r