1 /* Copyright (C) 2008 Vincent Penquerc'h.
2    This file is part of the Kate codec library.
3    Written by Vincent Penquerc'h.
4 
5    Use, distribution and reproduction of this library is governed
6    by a BSD style source license included with this source in the
7    file 'COPYING'. Please read these terms before distributing. */
8 
9 
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16 #if defined WIN32 || defined _WIN32 || defined MSDOS || defined __CYGWIN__ || defined __EMX__ || defined OS2
17 #include <io.h>
18 #include <fcntl.h>
19 #endif
20 #if defined WIN32 || defined _WIN32
21 #include <process.h>
22 #endif
23 #include <stdarg.h>
24 #include <stdio.h>
25 #ifdef HAVE_STDLIB_H
26 #include <stdlib.h>
27 #endif
28 #include <errno.h>
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #endif
32 #include <ogg/ogg.h>
33 #include "kate/oggkate.h"
34 #include "kate_internal.h"
35 #include "kutil.h"
36 #include "kstrings.h"
37 #include "kkate.h"
38 
39 #ifdef DEBUG
40 int write_bitmaps=0;
41 #endif
42 
write_kate_start(FILE * f)43 void write_kate_start(FILE *f)
44 {
45   fprintf(f,"kate {\n");
46 }
47 
write_kate_end(FILE * f)48 void write_kate_end(FILE *f)
49 {
50   fprintf(f,"}\n");
51 }
52 
write_text(FILE * f,const char * text,size_t len0,kate_markup_type text_markup_type)53 static void write_text(FILE *f,const char *text,size_t len0,kate_markup_type text_markup_type)
54 {
55   while (1) {
56     int ret=kate_text_get_character(kate_utf8,&text,&len0);
57     if (ret<0) {
58       fprintf(stderr,"Error getting character from text\n");
59       break;
60     }
61     if (ret==0) {
62       break;
63     }
64     else {
65       /* be conservative in what we encode */
66       const char *escape_list="";
67       switch (text_markup_type) {
68         case kate_markup_none: escape_list="\"\r\n`'|\\"; break;
69         case kate_markup_simple: escape_list="\"\r\n`'|\\"; break;
70         default: fprintf(stderr,"Unknown text markup type (%d)\n",text_markup_type); break;
71       }
72       if (ret>=32 && (ret>0xff || !strchr(escape_list,ret))) {
73         char utf8[12],*utf8ptr=utf8;
74         size_t wlen0=sizeof(utf8);
75         ret=kate_text_set_character(kate_utf8,ret,&utf8ptr,&wlen0);
76         if (ret<0) {
77           fprintf(stderr,"Error writing character\n");
78           break;
79         }
80         ret=kate_text_set_character(kate_utf8,0,&utf8ptr,&wlen0);
81         if (ret<0) {
82           fprintf(stderr,"Error writing character\n");
83           break;
84         }
85         fprintf(f,"%s",utf8);
86       }
87       else {
88         fprintf(f,"&#%u;",ret);
89       }
90     }
91   }
92 }
93 
write_color(FILE * f,const char * name,const kate_color * kc,size_t indent)94 static void write_color(FILE *f,const char *name,const kate_color *kc,size_t indent)
95 {
96   char *sindent=(char*)kate_malloc(1+indent);
97   size_t n;
98   for (n=0;n<indent;++n) sindent[n]=' ';
99   sindent[indent]=0;
100 
101   fprintf(f,"%s%s %d %d %d %d\n",sindent,name,kc->r,kc->g,kc->b,kc->a);
102 
103   kate_free(sindent);
104 }
105 
is_suitable_string(const char * value,size_t len)106 static int is_suitable_string(const char *value,size_t len)
107 {
108   const char *p;
109   int ret;
110   size_t n;
111   static const char *list="\"\r\n";
112 
113   ret=kate_text_validate(kate_utf8,value,len);
114   if (ret<0) return 0;
115   if (len>0) for (n=0;n<len-1;++n) if (!value[n]) return 0;
116   for (p=list;*p;++p) if (memchr(value,*p,len)) return 0;
117   return 1;
118 }
119 
write_metadata(FILE * f,const kate_meta * km,size_t indent)120 static void write_metadata(FILE *f,const kate_meta *km,size_t indent)
121 {
122   char *sindent=(char*)kate_malloc(1+indent);
123   size_t count,n,b;
124   int ret;
125 
126   for (n=0;n<indent;++n) sindent[n]=' ';
127   sindent[indent]=0;
128 
129   ret=kate_meta_query_count(km);
130   if (ret<0) {
131     fprintf(stderr,"Error retrieving medata: %d\n",ret);
132   }
133   else {
134     count=ret;
135     for (n=0;n<count;++n) {
136       const char *tag,*value;
137       size_t len;
138       ret=kate_meta_query(km,n,&tag,&value,&len);
139       if (ret<0) {
140         fprintf(stderr,"Error retrieving medata: %d\n",ret);
141       }
142       else {
143         fprintf(f,"%smeta \"%s\"=",sindent,tag);
144         if (is_suitable_string(value,len)) {
145           fprintf(f,"\"%s\"",value);
146         }
147         else {
148           fprintf(f," %lu {\n",(unsigned long)len);
149           for (b=0;b<len;++b) {
150             if (b%16==0) fprintf(f,"%s  ",sindent);
151             fprintf(f," 0x%02x",value[b]);
152             if (b%16==15 || b==len-1) fprintf(f,"\n");
153           }
154           fprintf(f,"%s}",sindent);
155         }
156         fprintf(f,"\n");
157       }
158     }
159   }
160 
161   kate_free(sindent);
162 }
163 
write_style_defs(FILE * f,const kate_style * ks,size_t indent)164 static void write_style_defs(FILE *f,const kate_style *ks,size_t indent)
165 {
166   char *sindent=(char*)kate_malloc(1+indent);
167   size_t n;
168   for (n=0;n<indent;++n) sindent[n]=' ';
169   sindent[indent]=0;
170 
171   {
172     const char *halign=halign2text(ks->halign);
173     const char *valign=valign2text(ks->valign);
174     kate_color tc=ks->text_color,bc=ks->background_color,dc=ks->draw_color;
175     fprintf(
176       f,
177       "%s%s %s\n",
178       sindent,halign,valign
179     );
180     write_color(f,"text color",&tc,indent);
181     write_color(f,"background color",&bc,indent);
182     write_color(f,"draw color",&dc,indent);
183     if (ks->font) {
184       fprintf(f,"%sfont \"%s\"\n",sindent,ks->font);
185     }
186     if (ks->font_width>=0 || ks->font_height>=0) {
187       if (ks->font_width==ks->font_height) {
188         fprintf(f,"%sfont size %f%s\n",sindent,ks->font_height,metric2suffix(ks->font_metric));
189       }
190       else {
191         if (ks->font_width>=0)
192           fprintf(f,"%sfont width %f%s\n",sindent,ks->font_width,metric2suffix(ks->font_metric));
193         if (ks->font_height>=0)
194         fprintf(f,"%sfont height %f%s\n",sindent,ks->font_height,metric2suffix(ks->font_metric));
195       }
196     }
197     if (ks->left_margin!=0 || ks->top_margin!=0 || ks->right_margin!=0 || ks->bottom_margin!=0) {
198       const char *margin_metric=metric2suffix(ks->margin_metric);
199       fprintf(
200         f,"%smargins %f%s %f%s %f%s %f%s\n",
201         sindent,
202         ks->left_margin,margin_metric,ks->top_margin,margin_metric,
203         ks->right_margin,margin_metric,ks->bottom_margin,margin_metric
204       );
205     }
206     if (ks->bold) fprintf(f,"%sbold\n",sindent);
207     if (ks->italics) fprintf(f,"%sitalics\n",sindent);
208     if (ks->underline) fprintf(f,"%sunderline\n",sindent);
209     if (ks->strike) fprintf(f,"%sstrike\n",sindent);
210     if (ks->justify) fprintf(f,"%sjustify\n",sindent);
211     fprintf(f,"%swrap %s\n",sindent,wrap2text(ks->wrap_mode));
212     if (ks->meta) write_metadata(f,ks->meta,indent);
213   }
214 
215   kate_free(sindent);
216 }
217 
write_region_defs(FILE * f,const kate_region * kr,size_t indent)218 static void write_region_defs(FILE *f,const kate_region *kr,size_t indent)
219 {
220   char *sindent=(char*)kate_malloc(1+indent);
221   size_t n;
222   for (n=0;n<indent;++n) sindent[n]=' ';
223   sindent[indent]=0;
224 
225   fprintf(f,"%s%s position %d %d size %d %d\n",sindent,metric2text(kr->metric),kr->x,kr->y,kr->w,kr->h);
226   if (kr->style>=0) fprintf(f,"%sdefault style %d\n",sindent,kr->style);
227   if (kr->clip) fprintf(f,"%sclip\n",sindent);
228   if (kr->meta) write_metadata(f,kr->meta,indent);
229 
230   kate_free(sindent);
231 }
232 
write_curve_defs(FILE * f,const kate_curve * kc,size_t indent)233 static void write_curve_defs(FILE *f,const kate_curve *kc,size_t indent)
234 {
235   char *sindent=(char*)kate_malloc(1+indent);
236   size_t n;
237   for (n=0;n<indent;++n) sindent[n]=' ';
238   sindent[indent]=0;
239 
240   fprintf(f,"%s%s\n",sindent,curve2text(kc->type));
241   if (kc->npts>0) {
242     size_t pt;
243     fprintf(f,"%s%lu points {\n",sindent,(unsigned long)kc->npts);
244     for (pt=0;pt<kc->npts;++pt) fprintf(f,"%s  %.16g %.16g\n",sindent,kc->pts[pt*2],kc->pts[pt*2+1]);
245     fprintf(f,"%s}\n",sindent);
246   }
247 
248   kate_free(sindent);
249 }
250 
write_motion_defs(FILE * f,const kate_info * ki,const kate_motion * km,size_t indent)251 static void write_motion_defs(FILE *f,const kate_info *ki,const kate_motion *km,size_t indent)
252 {
253   size_t s;
254   char *sindent=(char*)kate_malloc(1+indent);
255   size_t n;
256   for (n=0;n<indent;++n) sindent[n]=' ';
257   sindent[indent]=0;
258 
259   fprintf(f,"%ssemantics %s\n",sindent,semantics2text(km->semantics));
260   if (km->periodic) fprintf(f,"%speriodic\n",sindent);
261   if (km->x_mapping!=kate_motion_mapping_none || km->y_mapping!=kate_motion_mapping_none) {
262     if (km->x_mapping==km->y_mapping) {
263       fprintf(f,"%smapping %s\n",sindent,mapping2text(km->x_mapping));
264     }
265     else {
266       /* two calls as mapping2text can return a static buffer */
267       fprintf(f,"%smapping %s",sindent,mapping2text(km->x_mapping));
268       fprintf(f," %s\n",mapping2text(km->y_mapping));
269     }
270   }
271   for (s=0;s<km->ncurves;++s) {
272     const kate_curve *kc=km->curves[s];
273     int idx;
274     idx=kate_find_curve(ki,kc);
275     if (idx<0) {
276       fprintf(f,"%scurve {\n",sindent);
277       write_curve_defs(f,kc,indent+2);
278       fprintf(f,"%s}",sindent);
279     }
280     else {
281       fprintf(f,"%scurve %d",sindent,idx);
282     }
283     if (km->durations[s]!=-1) {
284       fprintf(f," for %.16g\n",km->durations[s]);
285     }
286     else {
287       fprintf(f,"\n");
288     }
289   }
290   if (km->meta) write_metadata(f,km->meta,indent);
291 
292   kate_free(sindent);
293 }
294 
write_palette_defs(FILE * f,const kate_palette * kp,size_t indent)295 static void write_palette_defs(FILE *f,const kate_palette *kp,size_t indent)
296 {
297   size_t s;
298   char *sindent=(char*)kate_malloc(1+indent);
299   size_t n;
300   for (n=0;n<indent;++n) sindent[n]=' ';
301   sindent[indent]=0;
302 
303   fprintf(f,"%s%lu colors {\n",sindent,(unsigned long)kp->ncolors);
304   for (s=0;s<kp->ncolors;++s) {
305     const kate_color *kc=kp->colors+s;
306     fprintf(f,"%s  { %d %d %d %d },\n",sindent,kc->r,kc->g,kc->b,kc->a);
307   }
308   fprintf(f,"%s}\n",sindent);
309   if (kp->meta) write_metadata(f,kp->meta,indent);
310 
311   kate_free(sindent);
312 }
313 
314 #ifdef DEBUG
315 
write_paletted_bitmap(const char * filename,const kate_bitmap * kb,const kate_palette * kp)316 static void write_paletted_bitmap(const char *filename,const kate_bitmap *kb,const kate_palette *kp)
317 {
318   size_t n,x,y;
319   FILE *f;
320 
321   f=fopen(filename,"w");
322   if (!f) {
323     fprintf(stderr,"Failed to open %s: %s\n",filename,strerror(errno));
324     return;
325   }
326 
327   fprintf(f,"P6\n%lu %lu\n255\n",(unsigned long)kb->width,(unsigned long)kb->height);
328   n=0;
329   for (y=0;y<kb->height;++y) {
330     for (x=0;x<kb->width;++x) {
331       int pix=kb->pixels[n++];
332       const kate_color *kc=kp->colors+pix;
333       fprintf(f,"%c%c%c",kc->r,kc->g,kc->b);
334     }
335   }
336 
337   fclose(f);
338 }
339 
write_png_bitmap(const char * filename,const kate_bitmap * kb)340 static void write_png_bitmap(const char *filename,const kate_bitmap *kb)
341 {
342   FILE *f;
343 
344   f=fopen(filename,"w");
345   if (!f) {
346     fprintf(stderr,"Failed to open %s: %s\n",filename,strerror(errno));
347     return;
348   }
349   fwrite(kb->pixels,kb->size,1,f);
350   fclose(f);
351 }
352 
353 #endif
354 
write_bitmap_defs(FILE * f,const kate_bitmap * kb,size_t indent)355 static void write_bitmap_defs(FILE *f,const kate_bitmap *kb,size_t indent)
356 {
357   size_t w,h,p;
358   char *sindent=(char*)kate_malloc(1+indent);
359   size_t n;
360   for (n=0;n<indent;++n) sindent[n]=' ';
361   sindent[indent]=0;
362 
363   switch (kb->type) {
364     case kate_bitmap_type_png:
365       fprintf(f,"%s%lux%lu png %lu {\n",sindent,(unsigned long)kb->width,(unsigned long)kb->height,(unsigned long)kb->size);
366       for (p=0;p<kb->size;++p) {
367         if (p%16==0) fprintf(f,"%s",sindent);
368         fprintf(f," 0x%02x",kb->pixels[p]);
369         if (p%16==15 || p==kb->size-1) fprintf(f,"\n");
370       }
371       fprintf(f,"%s}\n",sindent);
372       break;
373     case kate_bitmap_type_paletted:
374       fprintf(f,"%s%lux%lux%d {\n",sindent,(unsigned long)kb->width,(unsigned long)kb->height,kb->bpp);
375       p=0;
376       for (h=0;h<kb->height;++h) {
377         fprintf(f,"%s ",sindent);
378         for (w=0;w<kb->width;++w) {
379           fprintf(f," %3d",kb->pixels[p++]);
380         }
381         fprintf(f,"\n");
382       }
383       fprintf(f,"%s}\n",sindent);
384       break;
385     default:
386       fprintf(stderr,"Error: unknown bitmap type: %d\n",kb->type);
387       break;
388   }
389   if (kb->x_offset || kb->y_offset) {
390     fprintf(f,"%soffset %d %d\n",sindent,kb->x_offset,kb->y_offset);
391   }
392   if (kb->palette>=0) fprintf(f,"%sdefault palette %d\n",sindent,kb->palette);
393   if (kb->meta) write_metadata(f,kb->meta,indent);
394 
395   kate_free(sindent);
396 }
397 
write_font_range_defs(FILE * f,const kate_font_range * kfr,size_t indent)398 static void write_font_range_defs(FILE *f,const kate_font_range *kfr,size_t indent)
399 {
400   char *sindent=(char*)kate_malloc(1+indent);
401   size_t n;
402   for (n=0;n<indent;++n) sindent[n]=' ';
403   sindent[indent]=0;
404 
405   fprintf(f,"%sfirst code point 0x%x\n",sindent,kfr->first_code_point);
406   fprintf(f,"%slast code point 0x%x\n",sindent,kfr->last_code_point);
407   fprintf(f,"%sfirst bitmap %d\n",sindent,kfr->first_bitmap);
408 
409   kate_free(sindent);
410 }
411 
write_font_mapping_defs(FILE * f,const kate_info * ki,const kate_font_mapping * kfm,size_t indent)412 static void write_font_mapping_defs(FILE *f,const kate_info *ki,const kate_font_mapping *kfm,size_t indent)
413 {
414   char *sindent=(char*)kate_malloc(1+indent);
415   size_t n;
416   for (n=0;n<indent;++n) sindent[n]=' ';
417   sindent[indent]=0;
418 
419   for (n=0;n<kfm->nranges;++n) {
420     const kate_font_range *kfr=kfm->ranges[n];
421     int idx=kate_find_font_range(ki,kfr);
422     if (idx>=0) {
423       fprintf(f,"%srange %d\n",sindent,idx);
424     }
425     else {
426       fprintf(f,"%srange {\n",sindent);
427       write_font_range_defs(f,kfr,indent+2);
428       fprintf(f,"%s}\n",sindent);
429     }
430   }
431 
432   kate_free(sindent);
433 }
434 
write_granule_encoding(FILE * f,const kate_info * ki,size_t indent)435 static void write_granule_encoding(FILE *f,const kate_info *ki,size_t indent)
436 {
437   char *sindent=(char*)kate_malloc(1+indent);
438   size_t n;
439   for (n=0;n<indent;++n) sindent[n]=' ';
440   sindent[indent]=0;
441 
442   if (ki->gps_numerator!=1000 || ki->gps_denominator!=1) {
443     fprintf(f,"%sgranule rate %u/%u\n",sindent,ki->gps_numerator,ki->gps_denominator);
444   }
445   if (ki->granule_shift!=32) fprintf(f,"%sgranule shift %u\n",sindent,ki->granule_shift);
446 
447   kate_free(sindent);
448 }
449 
write_canvas_size(FILE * f,const kate_info * ki,size_t indent)450 static void write_canvas_size(FILE *f,const kate_info *ki,size_t indent)
451 {
452   char *sindent=(char*)kate_malloc(1+indent);
453   size_t n;
454   for (n=0;n<indent;++n) sindent[n]=' ';
455   sindent[indent]=0;
456 
457   if (ki->original_canvas_width>0 || ki->original_canvas_height>0) {
458     fprintf(f,"%scanvas size %lu %lu\n",sindent,(unsigned long)ki->original_canvas_width,(unsigned long)ki->original_canvas_height);
459   }
460 
461   kate_free(sindent);
462 }
463 
write_kate_headers(FILE * f,const kate_info * ki,const kate_comment * kc)464 void write_kate_headers(FILE *f,const kate_info *ki,const kate_comment *kc)
465 {
466   size_t n;
467   int c;
468 
469   fprintf(f,"\n");
470   fprintf(f,"  defs {\n");
471   write_granule_encoding(f,ki,4);
472   fprintf(f,"    category \"%s\"\n",ki->category);
473   fprintf(f,"    language \"%s\"\n",ki->language);
474   fprintf(f,"    directionality %s\n",directionality2text(ki->text_directionality));
475   write_canvas_size(f,ki,4);
476 
477   if (kc && kc->comments) {
478     fprintf(f,"\n");
479     for (c=0;c<kc->comments;++c) {
480       fprintf(f,"    comment   \"%s\"\n",kc->user_comments[c]);
481     }
482   }
483 
484   if (ki->nstyles) {
485     fprintf(f,"\n");
486     for (n=0;n<ki->nstyles;++n) {
487       const kate_style *ks=ki->styles[n];
488       fprintf(f,"    define style {\n");
489       write_style_defs(f,ks,6);
490       fprintf(f,"    }\n");
491     }
492   }
493 
494   if (ki->nregions) {
495     fprintf(f,"\n");
496     for (n=0;n<ki->nregions;++n) {
497       const kate_region *kr=ki->regions[n];
498       fprintf(f,"    define region {\n");
499       write_region_defs(f,kr,6);
500       fprintf(f,"    }\n");
501     }
502   }
503 
504   if (ki->ncurves) {
505     fprintf(f,"\n");
506     for (n=0;n<ki->ncurves;++n) {
507       const kate_curve *kc=ki->curves[n];
508       fprintf(f,"    define curve {\n");
509       write_curve_defs(f,kc,6);
510       fprintf(f,"    }\n");
511     }
512   }
513 
514   if (ki->nmotions) {
515     fprintf(f,"\n");
516     for (n=0;n<ki->nmotions;++n) {
517       const kate_motion *km=ki->motions[n];
518       fprintf(f,"    define motion {\n");
519       write_motion_defs(f,ki,km,6);
520       fprintf(f,"    }\n");
521     }
522   }
523 
524   if (ki->npalettes) {
525     fprintf(f,"\n");
526     for (n=0;n<ki->npalettes;++n) {
527       const kate_palette *kp=ki->palettes[n];
528       fprintf(f,"    define palette {\n");
529       write_palette_defs(f,kp,6);
530       fprintf(f,"    }\n");
531     }
532   }
533 
534   if (ki->nbitmaps) {
535     fprintf(f,"\n");
536     for (n=0;n<ki->nbitmaps;++n) {
537       const kate_bitmap *kb=ki->bitmaps[n];
538       fprintf(f,"    define bitmap {\n");
539       write_bitmap_defs(f,kb,6);
540       fprintf(f,"    }\n");
541     }
542   }
543 
544   if (ki->nfont_ranges) {
545     fprintf(f,"\n");
546     for (n=0;n<ki->nfont_ranges;++n) {
547       const kate_font_range *kfr=ki->font_ranges[n];
548       fprintf(f,"    define font range {\n");
549       write_font_range_defs(f,kfr,6);
550       fprintf(f,"    }\n");
551     }
552   }
553 
554   if (ki->nfont_mappings) {
555     fprintf(f,"\n");
556     for (n=0;n<ki->nfont_mappings;++n) {
557       const kate_font_mapping *kfm=ki->font_mappings[n];
558       fprintf(f,"    define font mapping {\n");
559       write_font_mapping_defs(f,ki,kfm,6);
560       fprintf(f,"    }\n");
561     }
562   }
563 
564   fprintf(f,"  }\n");
565   fprintf(f,"\n");
566 }
567 
write_kate_event(FILE * fout,void * data,const kate_event * ev,ogg_int64_t granpos)568 void write_kate_event(FILE *fout,void *data,const kate_event *ev,ogg_int64_t granpos)
569 {
570   const kate_info *ki=ev->ki;
571   float t0=ev->start_time;
572   float t1=ev->end_time;
573 
574   (void)data;
575   fprintf(fout,"  event {\n");
576   if (ev->id>=0) {
577     fprintf(fout,"    id %d\n",ev->id);
578   }
579   if (granpos>=0) {
580     kate_float base,offset;
581     kate_granule_split_time(ki,granpos,&base,&offset);
582 #ifdef DEBUG
583     fprintf(fout,"    # granule %llx composition: base %02d:%02d:%02.8g, offset %02d:%02d:%02.8g\n",
584       (long long)granpos,
585       time_hours(base),time_minutes(base),time_float_seconds(base),
586       time_hours(offset),time_minutes(offset),time_float_seconds(offset)
587     );
588 #endif
589   }
590   fprintf(fout,"    %02d:%02d:%02.8g --> %02d:%02d:%02.8g\n",
591     time_hours(t0),time_minutes(t0),time_float_seconds(t0),
592     time_hours(t1),time_minutes(t1),time_float_seconds(t1)
593   );
594   if (ev->language) {
595     fprintf(fout,"    language \"%s\"\n",ev->language);
596   }
597   if (ev->text_directionality!=ki->text_directionality) {
598     fprintf(fout,"    directionality %s\n",directionality2text(ev->text_directionality));
599   }
600   fprintf(fout,"    pre ");
601   switch (ev->text_markup_type) {
602     default: /* default to a sensible default */
603     case kate_markup_none: fprintf(fout,"text"); break;
604     case kate_markup_simple: fprintf(fout,"markup"); break;
605   }
606   fprintf(fout," \"");
607   write_text(fout,ev->text,ev->len0,ev->text_markup_type);
608   fprintf(fout,"\"\n");
609 
610   if (ev->nbitmaps>0) {
611     size_t n;
612     for (n=0;n<ev->nbitmaps;++n) {
613       const kate_bitmap *kb=ev->bitmaps[n];
614       int idx=kate_find_bitmap(ki,kb);
615       if (idx<0) {
616         fprintf(fout,"    define local bitmap {\n");
617         write_bitmap_defs(fout,kb,6);
618         fprintf(fout,"    }\n");
619       }
620       else {
621         fprintf(fout,"    define local bitmap = %d\n",idx);
622       }
623     }
624   }
625 
626   if (ev->region) {
627     int idx=kate_find_region(ki,ev->region);
628     if (idx<0) {
629       fprintf(fout,"    region {\n");
630       write_region_defs(fout,ev->region,6);
631       fprintf(fout,"    }\n");
632     }
633     else {
634       fprintf(fout,"    region %d\n",idx);
635     }
636   }
637   if (ev->style) {
638     int idx=kate_find_style(ki,ev->style);
639     if (idx<0) {
640       fprintf(fout,"    style {\n");
641       write_style_defs(fout,ev->style,6);
642       fprintf(fout,"    }\n");
643     }
644     else if (ev->region && idx!=ev->region->style) {
645       /* don't mention it if it's the region style, we don't want an override here */
646       fprintf(fout,"    style %d\n",idx);
647     }
648   }
649   if (ev->secondary_style) {
650     int idx=kate_find_style(ki,ev->secondary_style);
651     if (idx<0) {
652       fprintf(fout,"    secondary style {\n");
653       write_style_defs(fout,ev->secondary_style,6);
654       fprintf(fout,"    }\n");
655     }
656     else {
657       fprintf(fout,"    secondary style %d\n",idx);
658     }
659   }
660   if (ev->font_mapping) {
661     int idx=kate_find_font_mapping(ki,ev->font_mapping);
662     if (idx>=0) {
663       fprintf(fout,"    font mapping %d\n",idx);
664     }
665     else {
666       fprintf(fout,"    font mapping {\n");
667       write_font_mapping_defs(fout,ki,ev->font_mapping,6);
668       fprintf(fout,"    }\n");
669     }
670   }
671   if (ev->palette) {
672     int idx=kate_find_palette(ki,ev->palette);
673     if (idx<0) {
674       fprintf(fout,"    palette {\n");
675       write_palette_defs(fout,ev->palette,6);
676       fprintf(fout,"    }\n");
677     }
678     else {
679       fprintf(fout,"    palette %d\n",idx);
680     }
681   }
682   if (ev->bitmap) {
683     int idx=kate_find_bitmap(ki,ev->bitmap);
684     if (idx<0) {
685       fprintf(fout,"    bitmap {\n");
686       write_bitmap_defs(fout,ev->bitmap,6);
687       fprintf(fout,"    }\n");
688     }
689     else {
690       fprintf(fout,"    bitmap %d\n",idx);
691     }
692   }
693 #ifdef DEBUG
694   if (write_bitmaps && ev->bitmap) {
695     static int n=0;
696     static char filename[32];
697     switch (ev->bitmap->type) {
698       case kate_bitmap_type_paletted:
699         if (ev->bitmap->bpp>0 && ev->palette) {
700           snprintf(filename,sizeof(filename),"/tmp/kate-bitmap-%d",n++);
701           filename[sizeof(filename)-1]=0;
702           write_paletted_bitmap(filename,ev->bitmap,ev->palette);
703         }
704         break;
705       case kate_bitmap_type_png:
706         snprintf(filename,sizeof(filename),"/tmp/kate-bitmap-%d",n++);
707         filename[sizeof(filename)-1]=0;
708         write_png_bitmap(filename,ev->bitmap);
709         break;
710     }
711   }
712 #endif
713   if (ev->nmotions) {
714     size_t m;
715     for (m=0;m<ev->nmotions;++m) {
716       const kate_motion *km=ev->motions[m];
717       int idx=kate_find_motion(ki,km);
718       if (idx<0) {
719         fprintf(fout,"    motion {\n");
720         write_motion_defs(fout,ki,km,6);
721         fprintf(fout,"    }\n");
722       }
723       else {
724         fprintf(fout,"    motion %d\n",idx);
725       }
726     }
727   }
728   if (ev->meta) write_metadata(fout,ev->meta,4);
729   fprintf(fout,"  }\n");
730   fprintf(fout,"\n");
731 }
732 
733