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 %{
11 
12 #define KATE_INTERNAL
13 #include "kate_internal.h"
14 
15 #include <limits.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <stdarg.h>
19 #ifdef HAVE_STRING_H
20 #include <string.h>
21 #endif
22 #include <ctype.h>
23 #include "kate/oggkate.h"
24 #ifdef HAVE_PNG
25 #include "kpng.h"
26 #endif
27 #include "katedesc.h"
28 #include "kate_parser.h"
29 
30 #define CHECK_KATE_API_ERROR(statement) \
31   do {                                  \
32     int ret=(statement);                \
33     if (ret<0) {                        \
34       yyerror("error in #statement");   \
35       exit(-1);                         \
36     }                                   \
37   } while(0)
38 
39 int nerrors=0;
40 int nwarnings=0;
41 
42 static char *temp_macro_name=NULL;
43 static kate_float timebase = (kate_float)0;
44 
45 typedef kate_style kd_style;
46 typedef kate_region kd_region;
47 
48 typedef struct kd_curve {
49   size_t idx;
50   kate_curve *curve;
51 } kd_curve;
52 
53 typedef struct kd_motion {
54   size_t idx;
55   kate_motion *motion;
56 } kd_motion;
57 
58 typedef struct kd_palette {
59   kate_palette *palette;
60 } kd_palette;
61 
62 typedef struct kd_bitmap {
63   kate_bitmap *bitmap;
64 } kd_bitmap;
65 
66 static kate_style kstyle;
67 static kate_region kregion;
68 static kd_palette kpalette;
69 static kd_bitmap kbitmap;
70 static kd_curve kcurve;
71 static kate_font_range *krange=NULL;
72 static kate_font_mapping *kmapping=NULL;
73 
74 static size_t nkmotions=0;
75 static kd_motion *kmotions=NULL;
76 static kate_motion *kmotion=NULL;
77 
78 static char **style_names=NULL;
79 static char **region_names=NULL;
80 static char **palette_names=NULL;
81 static char **bitmap_names=NULL;
82 static char **curve_names=NULL;
83 static char **motion_names=NULL;
84 static char **font_range_names=NULL;
85 static char **font_mapping_names=NULL;
86 
87 static size_t n_local_bitmaps=0;
88 static char **local_bitmap_names=NULL;
89 static kate_bitmap **local_bitmaps=NULL;
90 
91 static int open_ended_curve=0;
92 static int n_curve_pts=-1;
93 static int n_palette_colors=-1;
94 static int n_bitmap_pixels=-1;
95 static size_t n_bytes_in_stream=0;
96 static char *byte_stream=NULL;
97 static size_t byte_stream_size=0;
98 
99 static kate_float karaoke_base_height=(kate_float)0;
100 static kate_float karaoke_top_height=(kate_float)0;
101 
102 typedef struct kd_event {
103   kate_float t0;
104   kate_float t1;
105   kate_float duration;
106   char *text;
107   kate_markup_type text_markup_type;
108   int region_index;
109   const kate_region *region;
110   int style_index;
111   const kate_style *style;
112   int secondary_style_index;
113   const kate_style *secondary_style;
114   int palette_index;
115   const kate_palette *palette;
116   int bitmap_index;
117   const kate_bitmap *bitmap;
118 } kd_event;
119 static kd_event kevent;
120 
katedesc_trace(const char * msg,...)121 static void katedesc_trace(const char *msg,...)
122 {
123   va_list ap;
124   va_start(ap,msg);
125   vfprintf(stderr,msg,ap);
126   va_end(ap);
127 }
128 /* #define KDTRACE(msg,args...) katedesc_trace(msg, ##args) */
129 #define KDTRACE katedesc_trace
130 
yyerror(const char * s)131 int yyerror(const char *s)
132 {
133   (void)s;
134   KDTRACE("Error line %d: %s (token %s)\n",nlines,s,katedesc_text);
135   nerrors++;
136   return 1;
137 }
138 
yyerrorf(const char * msg,...)139 int yyerrorf(const char *msg,...)
140 {
141   static char buffer[4096];
142   va_list ap;
143   va_start(ap,msg);
144   vsnprintf(buffer,sizeof(buffer),msg,ap);
145   buffer[sizeof(buffer)-1]=0;
146   va_end(ap);
147   return yyerror(buffer);
148 }
149 
yywarning(const char * s)150 int yywarning(const char *s)
151 {
152   (void)s;
153   KDTRACE("Warning line %d: %s (token %s)\n",nlines,s,katedesc_text);
154   nwarnings++;
155   return 1;
156 }
157 
add_meta(kate_meta ** km,const char * tag,const char * value)158 static void add_meta(kate_meta **km,const char *tag,const char *value)
159 {
160   if (!*km) {
161     CHECK_KATE_API_ERROR(kate_meta_create(km));
162   }
163   CHECK_KATE_API_ERROR(kate_meta_add_string(*km,tag,value));
164 }
165 
add_meta_byte_stream(kate_meta ** km,const char * tag)166 static void add_meta_byte_stream(kate_meta **km,const char *tag)
167 {
168   if (!*km) {
169     CHECK_KATE_API_ERROR(kate_meta_create(km));
170   }
171   CHECK_KATE_API_ERROR(kate_meta_add(*km,tag,byte_stream,byte_stream_size));
172 
173   kate_free(byte_stream);
174   byte_stream=NULL;
175   n_bytes_in_stream=0;
176   byte_stream_size=0;
177 }
178 
catstrings(char * s1,const char * s2)179 static char *catstrings(char *s1,const char *s2)
180 {
181   size_t len;
182   char *s;
183 
184   if (!s2) { yyerror("internal error: no string to append"); exit(-1); }
185   len=(s1?strlen(s1):0)+strlen(s2)+1;
186   s=(char*)kate_realloc(s1,len);
187   if (!s) { yyerror("out of memory"); exit(-1); }
188   if (s1) strcat(s,s2); else strcpy(s,s2);
189 
190   return s;
191 }
192 
dupstring(const char * s)193 static char *dupstring(const char *s)
194 {
195   size_t len;
196   char *news;
197 
198   if (!s) { yyerror("internal error: no string"); exit(-1); }
199 
200   len=strlen(s);
201   news=(char*)kate_malloc(len+1);
202   if (!news) { yyerror("out of memory"); exit(-1); }
203   memcpy(news,s,len+1);
204   return news;
205 }
206 
find_item(const char * name,size_t nnames,char ** names)207 static int find_item(const char *name,size_t nnames,char **names)
208 {
209   size_t n;
210   for (n=0;n<nnames;++n) {
211     if (names[n] && !strcmp(names[n],name)) return n;
212   }
213   yyerrorf("Named item not found: %s",name);
214   return 0;
215 }
216 
init_palette(void)217 static void init_palette(void)
218 {
219   kpalette.palette=(kate_palette*)kate_malloc(sizeof(kate_palette));
220   if (!kpalette.palette) { yyerror("out of memory"); exit(-1); }
221   if (kate_palette_init(kpalette.palette)<0) {
222     yyerror("palette init failed");
223     exit(-1);
224   }
225 }
226 
generate_full_filename(char * full_filename,size_t size,const char * filename)227 static void generate_full_filename(char *full_filename,size_t size,const char *filename)
228 {
229   if (filename[0]=='/' || filename[0]=='\\') {
230     strcpy(full_filename,filename);
231   }
232   else {
233     snprintf(full_filename,size,"%s%s",base_path,filename);
234     full_filename[size-1]=0;
235   }
236 }
237 
load_palette(const char * filename)238 static void load_palette(const char *filename)
239 {
240 #ifdef HAVE_PNG
241   int ncolors;
242   kate_color *palette=NULL;
243   static char full_filename[4096];
244 
245   generate_full_filename(full_filename,sizeof(full_filename),filename);
246   if (kd_read_png8(full_filename,NULL,NULL,NULL,&palette,&ncolors,NULL)) {
247     yyerrorf("failed to load %s",filename);
248     return;
249   }
250 
251   kpalette.palette->ncolors=ncolors;
252   kpalette.palette->colors=palette;
253 #else
254   yyerrorf("PNG support not compiled in: cannot load %s",filename);
255   exit(-1);
256 #endif
257 }
258 
check_palette(const kate_palette * kp)259 static void check_palette(const kate_palette *kp)
260 {
261   if (!kp) { yyerror("internal error: no palette"); exit(-1); }
262 }
263 
add_palette(kate_info * ki,const char * name,kate_palette * kp)264 static void add_palette(kate_info *ki,const char *name,kate_palette *kp)
265 {
266   int ret;
267 
268   check_palette(kp);
269 
270   ret=kate_info_add_palette(ki,kp);
271   if (ret<0) {
272     yyerrorf("Failed to register palette: %d",ret);
273   }
274   else {
275     palette_names=(char**)kate_realloc(palette_names,ki->npalettes*sizeof(char*));
276     if (!palette_names) {
277       yyerror("Out of memory");
278       exit(-1);
279     }
280     palette_names[ki->npalettes-1]=name?dupstring(name):NULL;
281   }
282 }
283 
find_palette(const kate_info * ki,const char * name)284 static int find_palette(const kate_info *ki,const char *name)
285 {
286   return find_item(name,ki->npalettes,palette_names);
287 }
288 
init_bitmap(void)289 static void init_bitmap(void)
290 {
291   kbitmap.bitmap=(kate_bitmap*)kate_malloc(sizeof(kate_bitmap));
292   if (!kbitmap.bitmap) { yyerror("out of memory"); exit(-1); }
293   if (kate_bitmap_init_new(kbitmap.bitmap)<0) {
294     yyerror("bitmap init failed");
295     exit(-1);
296   }
297 }
298 
compute_bitmap_x_offset(kate_float percent)299 static int compute_bitmap_x_offset(kate_float percent)
300 {
301   if (kbitmap.bitmap->width) {
302     return (int)(kbitmap.bitmap->width*percent/100+0.5);
303   }
304   else {
305     yyerror("Bitmap width must be known before specifying offset as a percentage");
306     return 0;
307   }
308 }
309 
compute_bitmap_y_offset(kate_float percent)310 static int compute_bitmap_y_offset(kate_float percent)
311 {
312   if (kbitmap.bitmap->height) {
313     return (int)(kbitmap.bitmap->height*percent/100+0.5);
314   }
315   else {
316     yyerror("Bitmap height must be known before specifying offset as a percentage");
317     return 0;
318   }
319 }
320 
load_bitmap(const char * filename,int paletted)321 static void load_bitmap(const char *filename,int paletted)
322 {
323 #ifdef HAVE_PNG
324   int w,h;
325   unsigned char *pixels=NULL;
326 
327   if (paletted) {
328     int bpp;
329     static char full_filename[4096];
330 
331     generate_full_filename(full_filename,sizeof(full_filename),filename);
332     if (kd_read_png8(full_filename,&w,&h,&bpp,NULL,NULL,&pixels)) {
333       yyerrorf("failed to load %s",filename);
334       return;
335     }
336 
337     kbitmap.bitmap->type=kate_bitmap_type_paletted;
338     kbitmap.bitmap->width=w;
339     kbitmap.bitmap->height=h;
340     kbitmap.bitmap->bpp=bpp;
341     kbitmap.bitmap->pixels=pixels;
342     kbitmap.bitmap->size=0;
343   }
344   else {
345     size_t size;
346     static char full_filename[4096];
347 
348     generate_full_filename(full_filename,sizeof(full_filename),filename);
349     if (kd_read_png(full_filename,&w,&h,&pixels,&size)) {
350       yyerrorf("failed to load %s",filename);
351       return;
352     }
353 
354     kbitmap.bitmap->type=kate_bitmap_type_png;
355     kbitmap.bitmap->width=w;
356     kbitmap.bitmap->height=h;
357     kbitmap.bitmap->bpp=0;
358     kbitmap.bitmap->pixels=pixels;
359     kbitmap.bitmap->size=size;
360   }
361 
362   kbitmap.bitmap->palette=-1;
363 #else
364   (void)paletted;
365   yyerrorf("PNG support not compiled in: cannot load %s",filename);
366   exit(-1);
367 #endif
368 }
369 
check_bitmap(const kate_bitmap * kb)370 static void check_bitmap(const kate_bitmap *kb)
371 {
372   if (!kb) { yyerror("internal error: no bitmap"); exit(-1); }
373 }
374 
add_bitmap(kate_info * ki,const char * name,kate_bitmap * kb)375 static void add_bitmap(kate_info *ki,const char *name,kate_bitmap *kb)
376 {
377   int ret;
378 
379   check_bitmap(kb);
380 
381   ret=kate_info_add_bitmap(ki,kb);
382   if (ret<0) {
383     yyerrorf("Failed to register bitmap: %d",ret);
384   }
385   else {
386     bitmap_names=(char**)kate_realloc(bitmap_names,ki->nbitmaps*sizeof(char*));
387     if (!bitmap_names) {
388       yyerror("Out of memory");
389       exit(-1);
390     }
391     bitmap_names[ki->nbitmaps-1]=name?dupstring(name):NULL;
392   }
393 }
394 
add_local_bitmap(kate_state * k,const char * name,kate_bitmap * kb)395 static void add_local_bitmap(kate_state *k,const char *name,kate_bitmap *kb)
396 {
397   int ret;
398 
399   check_bitmap(kb);
400 
401   ret=kate_encode_add_bitmap(k,kb);
402   if (ret<0) {
403     yyerrorf("Failed to register bitmap: %d",ret);
404   }
405   else {
406     ++n_local_bitmaps;
407     local_bitmap_names=(char**)kate_realloc(local_bitmap_names,n_local_bitmaps*sizeof(char*));
408     if (!local_bitmap_names) {
409       yyerror("Out of memory");
410       exit(-1);
411     }
412     local_bitmap_names[n_local_bitmaps-1]=name?dupstring(name):NULL;
413     local_bitmaps=(kate_bitmap**)kate_realloc(local_bitmaps,n_local_bitmaps*sizeof(kate_bitmap*));
414     if (!local_bitmaps) {
415       yyerror("Out of memory");
416       exit(-1);
417     }
418     local_bitmaps[n_local_bitmaps-1]=kb;
419   }
420 }
421 
add_local_bitmap_index(kate_state * k,const char * name,size_t idx)422 static void add_local_bitmap_index(kate_state *k,const char *name,size_t idx)
423 {
424   int ret;
425 
426   ret=kate_encode_add_bitmap_index(k,idx);
427   if (ret<0) {
428     yyerrorf("Failed to register bitmap: %d",ret);
429   }
430   else {
431     ++n_local_bitmaps;
432     local_bitmap_names=(char**)kate_realloc(local_bitmap_names,n_local_bitmaps*sizeof(char*));
433     if (!local_bitmap_names) {
434       yyerror("Out of memory");
435       exit(-1);
436     }
437     local_bitmap_names[n_local_bitmaps-1]=name?dupstring(name):NULL;
438     local_bitmaps=(kate_bitmap**)kate_realloc(local_bitmaps,n_local_bitmaps*sizeof(kate_bitmap*));
439     if (!local_bitmaps) {
440       yyerror("Out of memory");
441       exit(-1);
442     }
443     local_bitmaps[n_local_bitmaps-1]=NULL;
444   }
445 }
446 
find_bitmap(const kate_info * ki,const char * name)447 static int find_bitmap(const kate_info *ki,const char *name)
448 {
449   int ret=find_item(name,ki->nbitmaps,bitmap_names);
450   if (ret>=0) return ret;
451   ret=find_item(name,n_local_bitmaps,local_bitmap_names);
452   if (ret>=0) return ret+ki->nbitmaps;
453   return ret;
454 }
455 
check_style(const kate_style * ks)456 static void check_style(const kate_style *ks)
457 {
458   if (!ks) { yyerror("internal error: no style"); exit(-1); }
459 }
460 
add_style(kate_info * ki,const char * name,const kate_style * ks)461 static void add_style(kate_info *ki,const char *name,const kate_style *ks)
462 {
463   int ret;
464   kate_style *ks2;
465 
466   check_style(ks);
467 
468   ks2=(kate_style*)kate_malloc(sizeof(*ks2));
469   if (!ks2) {
470     yyerrorf("Out of memory");
471     exit(-1);
472   }
473   memcpy(ks2,ks,sizeof(*ks2));
474 
475   ret=kate_info_add_style(ki,ks2);
476   if (ret<0) {
477     yyerrorf("Failed to register style: %d",ret);
478   }
479   else {
480     style_names=(char**)kate_realloc(style_names,ki->nstyles*sizeof(char*));
481     if (!style_names) {
482       yyerror("Out of memory");
483       exit(-1);
484     }
485     style_names[ki->nstyles-1]=name?dupstring(name):NULL;
486   }
487 }
488 
find_style(const kate_info * ki,const char * name)489 static int find_style(const kate_info *ki,const char *name)
490 {
491   return find_item(name,ki->nstyles,style_names);
492 }
493 
check_region(const kate_region * kr)494 static void check_region(const kate_region *kr)
495 {
496   if (!kr) { yyerror("internal error: no region"); exit(-1); }
497   if (kr->w<0) yyerrorf("Region width (%d) must be non negative",kr->w);
498   if (kr->h<0) yyerrorf("Region height (%d) must be non negative",kr->h);
499 }
500 
add_region(kate_info * ki,const char * name,const kate_region * kr)501 static void add_region(kate_info *ki,const char *name,const kate_region *kr)
502 {
503   int ret;
504   kate_region *kr2;
505 
506   check_region(kr);
507 
508   kr2=(kate_region*)kate_malloc(sizeof(*kr2));
509   if (!kr2) {
510     yyerrorf("Out of memory");
511     exit(-1);
512   }
513   memcpy(kr2,kr,sizeof(*kr2));
514 
515   ret=kate_info_add_region(ki,kr2);
516   if (ret<0) {
517     yyerrorf("Failed to register region: %d",ret);
518   }
519   else {
520     region_names=(char**)kate_realloc(region_names,ki->nregions*sizeof(char*));
521     if (!region_names) {
522       yyerror("Out of memory");
523       exit(-1);
524     }
525     region_names[ki->nregions-1]=name?dupstring(name):NULL;
526   }
527 }
528 
find_region(const kate_info * ki,const char * name)529 static int find_region(const kate_info *ki,const char *name)
530 {
531   return find_item(name,ki->nregions,region_names);
532 }
533 
check_curve(const kate_curve * kc)534 static void check_curve(const kate_curve *kc)
535 {
536   size_t minpts=0,maxpts=INT_MAX;
537   if (!kc) { yyerror("internal error: no curve"); exit(-1); }
538   switch (kc->type) {
539     case kate_curve_none: minpts=0; maxpts=0; break;
540     case kate_curve_static: minpts=1; maxpts=1; break;
541     case kate_curve_linear: minpts=2; maxpts=INT_MAX; break;
542     case kate_curve_catmull_rom_spline: minpts=2; maxpts=INT_MAX; break;
543     case kate_curve_bezier_cubic_spline: minpts=3; maxpts=INT_MAX; break;
544     case kate_curve_bspline: minpts=2; maxpts=INT_MAX; break;
545   }
546   if (kc->npts<minpts) yyerrorf("Curve does not have enough points for this type (has %d, min pts %d)",kc->npts,minpts);
547   if (kc->npts>maxpts) yyerrorf("Curve has too many points for this type (has %d, max pts %d)",kc->npts,maxpts);
548   if (kc->type==kate_curve_bezier_cubic_spline) {
549     if ((kc->npts-1)%3) yyerrorf("Cubic Bezier splines should have 1+3n points");
550   }
551 }
552 
add_curve(kate_info * ki,const char * name,kate_curve * kc)553 static void add_curve(kate_info *ki,const char *name,kate_curve *kc)
554 {
555   int ret;
556 
557   check_curve(kc);
558 
559   ret=kate_info_add_curve(ki,kc);
560   if (ret<0) {
561     yyerrorf("Failed to register curve: %d",ret);
562   }
563   else {
564     curve_names=(char**)kate_realloc(curve_names,ki->ncurves*sizeof(char*));
565     if (!curve_names) {
566       yyerror("Out of memory");
567       exit(-1);
568     }
569     curve_names[ki->ncurves-1]=name?dupstring(name):NULL;
570   }
571 }
572 
find_curve(const kate_info * ki,const char * name)573 static int find_curve(const kate_info *ki,const char *name)
574 {
575   return find_item(name,ki->ncurves,curve_names);
576 }
577 
clear_motions(void)578 static void clear_motions(void)
579 {
580   kate_free(kmotions);
581   kmotions=NULL;
582   kmotion=NULL;
583   nkmotions=0;
584 }
585 
check_motion(kate_motion * kmotion)586 static void check_motion(kate_motion *kmotion)
587 {
588   if (!kmotion) { yyerror("internal error: no motion"); exit(-1); }
589 
590   if (kmotion->ncurves==0) { yyerror("motion must have at least one curve"); return; }
591   if (kmotion->semantics==(kate_motion_semantics)-1) { yyerror("motion semantics is not defined"); return; }
592 }
593 
add_motion(kate_info * ki,const char * name,kate_motion * km)594 static void add_motion(kate_info *ki,const char *name,kate_motion *km)
595 {
596   int ret;
597 
598   check_motion(km);
599 
600   ret=kate_info_add_motion(ki,km);
601   if (ret<0) {
602     yyerrorf("Failed to register motion: %d",ret);
603   }
604   else {
605     motion_names=(char**)kate_realloc(motion_names,ki->nmotions*sizeof(char*));
606     if (!motion_names) {
607       yyerror("Out of memory");
608       exit(-1);
609     }
610     motion_names[ki->nmotions-1]=name?dupstring(name):NULL;
611   }
612 
613   clear_motions();
614 }
615 
find_motion(const kate_info * ki,const char * name)616 static int find_motion(const kate_info *ki,const char *name)
617 {
618   return find_item(name,ki->nmotions,motion_names);
619 }
620 
init_style(kd_style * style)621 static void init_style(kd_style *style)
622 {
623   int ret=kate_style_init(style);
624   if (ret<0) {
625     yyerrorf("Error initializing style: %d\n",ret);
626     exit(1);
627   }
628 }
629 
set_font_width(kd_style * style,kate_float s,kate_space_metric metric)630 static void set_font_width(kd_style *style,kate_float s,kate_space_metric metric)
631 {
632   if (style->font_width>=0) {
633     yyerror("Font width already set");
634   }
635   if (style->font_height>=0 && style->font_metric!=metric) {
636     yyerror("All font size metrics must be the same");
637   }
638   style->font_width=s;
639   style->font_metric=metric;
640 }
641 
set_font_height(kd_style * style,kate_float s,kate_space_metric metric)642 static void set_font_height(kd_style *style,kate_float s,kate_space_metric metric)
643 {
644   if (style->font_height>=0) {
645     yyerror("Font height already set");
646   }
647   if (style->font_width>=0 && style->font_metric!=metric) {
648     yyerror("All font size metrics must be the same");
649   }
650   style->font_height=s;
651   style->font_metric=metric;
652 }
653 
set_font(kd_style * style,const char * font)654 static void set_font(kd_style *style,const char *font)
655 {
656   size_t len;
657   if (!font) {
658     yyerror("Internal error: no font");
659     exit(-1);
660   }
661   len=strlen(font);
662   if (style->font) {
663     yyerror("Font already set");
664   }
665   style->font=(char*)kate_malloc(len+1);
666   if (!style->font) {
667     yyerror("out of memory");
668     exit(-1);
669   }
670   strcpy(style->font,font);
671 }
672 
set_font_size(kd_style * style,kate_float s,kate_space_metric metric)673 static void set_font_size(kd_style *style,kate_float s,kate_space_metric metric)
674 {
675   if (style->font_height>=0 || style->font_width>=0) {
676     yyerror("Font width and/or height already set");
677   }
678   style->font_width=s;
679   style->font_height=s;
680   style->font_metric=metric;
681 }
682 
set_margin(kd_style * style,kate_float * margin,kate_float m,kate_space_metric metric)683 static void set_margin(kd_style *style,kate_float *margin,kate_float m,kate_space_metric metric)
684 {
685   int metric_already_set=0;
686   if (&style->left_margin!=margin && style->left_margin!=0) metric_already_set=1;
687   if (&style->top_margin!=margin && style->top_margin!=0) metric_already_set=1;
688   if (&style->right_margin!=margin && style->right_margin!=0) metric_already_set=1;
689   if (&style->bottom_margin!=margin && style->bottom_margin!=0) metric_already_set=1;
690   if (metric_already_set && metric!=style->margin_metric) {
691     yyerror("Metric must be the same for all margins");
692     return;
693   }
694   *margin=m;
695   style->margin_metric=metric;
696 }
697 
set_margins(kd_style * style,kate_float left,kate_space_metric left_metric,kate_float top,kate_space_metric top_metric,kate_float right,kate_space_metric right_metric,kate_float bottom,kate_space_metric bottom_metric)698 static void set_margins(kd_style *style,
699                         kate_float left,kate_space_metric left_metric,
700                         kate_float top,kate_space_metric top_metric,
701                         kate_float right,kate_space_metric right_metric,
702                         kate_float bottom,kate_space_metric bottom_metric)
703 {
704   if (left_metric!=right_metric || left_metric!=top_metric || left_metric!=bottom_metric) {
705     yyerror("Metric must be the same for all margins");
706     return;
707   }
708   style->left_margin=left;
709   style->top_margin=top;
710   style->right_margin=right;
711   style->bottom_margin=bottom;
712   style->margin_metric=left_metric;
713 }
714 
init_style_from(int idx)715 static void init_style_from(int idx)
716 {
717   const kate_style *from=ki.styles[idx];
718   init_style(&kstyle);
719   memcpy(&kstyle,from,sizeof(kate_style));
720 }
721 
init_region(kd_region * region)722 static void init_region(kd_region *region)
723 {
724   int ret=kate_region_init(region);
725   if (ret<0) {
726     yyerrorf("Error initializing region: %d\n",ret);
727     exit(1);
728   }
729 }
730 
init_region_from(int idx)731 static void init_region_from(int idx)
732 {
733   const kate_region *from=ki.regions[idx];
734   init_region(&kregion);
735   memcpy(&kregion,from,sizeof(kate_region));
736 }
737 
reference_curve_from(int idx)738 static void reference_curve_from(int idx)
739 {
740   kcurve.idx=idx;
741   kcurve.curve=NULL;
742 }
743 
init_curve(void)744 static void init_curve(void)
745 {
746   kcurve.idx=0;
747   kcurve.curve=(kate_curve*)kate_malloc(sizeof(kate_curve));
748   if (!kcurve.curve) { yyerror("out of memory"); exit(-1); }
749   if (kate_curve_init(kcurve.curve)<0) {
750     yyerror("error initializing curve");
751     exit(-1);
752   }
753 }
754 
init_curve_from(int idx)755 static void init_curve_from(int idx)
756 {
757   const kate_curve *from=ki.curves[idx];
758   if (!from || !from->pts) {
759     yyerror("invalid curve to init from");
760     exit(-1);
761   }
762   init_curve();
763   memcpy(kcurve.curve,from,sizeof(kate_curve));
764   kcurve.curve->pts=(kate_float*)kate_malloc(kcurve.curve->npts*2*sizeof(kate_float));
765   if (!kcurve.curve->pts) {
766     yyerror("out of memory");
767     exit(-1);
768   }
769   memcpy(kcurve.curve->pts,from->pts,kcurve.curve->npts*2*sizeof(kate_float));
770 }
771 
init_curve_points(int npts)772 static void init_curve_points(int npts)
773 {
774   if (!kcurve.curve) { yyerror("internal error: curve not initialized"); exit(-1); }
775   if (n_curve_pts<0) { katedesc_error("Curve type must be specified before the points"); exit(-1); }
776   if (npts<=0) { katedesc_error("Number of points cannot be negative or zero"); exit(-1); }
777   kcurve.curve->npts=npts;
778   kcurve.curve->pts=(kate_float*)kate_malloc(npts*2*sizeof(kate_float));
779   if (!kcurve.curve->pts) {
780     yyerror("Out of memory");
781     exit(-1);
782   }
783   open_ended_curve=0;
784 }
785 
init_open_ended_curve_points(void)786 static void init_open_ended_curve_points(void)
787 {
788   if (!kcurve.curve) { yyerror("internal error: curve not initialized"); exit(-1); }
789   if (n_curve_pts<0) katedesc_error("Curve type must be specified before the points");
790   kcurve.curve->npts=0;
791   kcurve.curve->pts=NULL;
792   open_ended_curve=1;
793 }
794 
add_open_ended_curve_point(kate_float pt)795 static void add_open_ended_curve_point(kate_float pt)
796 {
797   if (!kcurve.curve) { yyerror("internal error: curve not initialized"); exit(-1); }
798   ++n_curve_pts;
799   kcurve.curve->npts=(n_curve_pts+1)/2;
800   kcurve.curve->pts=(kate_float*)kate_realloc(kcurve.curve->pts,kcurve.curve->npts*2*sizeof(kate_float));
801   if (!kcurve.curve->pts) {
802     yyerror("Out of memory");
803     exit(-1);
804   }
805   kcurve.curve->pts[n_curve_pts-1]=pt;
806 }
807 
init_palette_colors(int ncolors)808 static void init_palette_colors(int ncolors)
809 {
810   if (!kpalette.palette) { yyerror("internal error: palette not initialized"); exit(-1); }
811   kpalette.palette->ncolors=ncolors;
812   kpalette.palette->colors=(kate_color*)kate_malloc(ncolors*sizeof(kate_color));
813   if (!kpalette.palette->colors) {
814     yyerror("Out of memory");
815     exit(-1);
816   }
817   n_palette_colors=0;
818 }
819 
init_bitmap_pixels(int width,int height,int bpp)820 static void init_bitmap_pixels(int width,int height,int bpp)
821 {
822   if (!kbitmap.bitmap) { yyerror("internal error: bitmap not initialized"); exit(-1); }
823   if (width<=0 || height<=0) yyerror("Bitmap dimensions must be positive");
824   if (bpp<=0) yyerror("Bitmap bit depth must be positive");
825   if (bpp>8) yyerrorf("Bitmap bit depth must not be more than 8 (is %d)",bpp);
826   kbitmap.bitmap->type=kate_bitmap_type_paletted;
827   kbitmap.bitmap->width=width;
828   kbitmap.bitmap->height=height;
829   kbitmap.bitmap->bpp=bpp;
830   kbitmap.bitmap->pixels=(unsigned char*)kate_malloc(width*height*sizeof(unsigned char));
831   if (!kbitmap.bitmap->pixels) {
832     yyerror("Out of memory");
833     exit(-1);
834   }
835   kbitmap.bitmap->size=0;
836   n_bitmap_pixels=0;
837 }
838 
init_png_bitmap_pixels(int width,int height,int size)839 static void init_png_bitmap_pixels(int width,int height,int size)
840 {
841   if (!kbitmap.bitmap) { yyerror("internal error: bitmap not initialized"); exit(-1); }
842   if (width<=0 || height<=0) yyerror("Bitmap dimensions must be positive");
843   kbitmap.bitmap->type=kate_bitmap_type_png;
844   kbitmap.bitmap->width=width;
845   kbitmap.bitmap->height=height;
846   kbitmap.bitmap->bpp=0;
847   kbitmap.bitmap->pixels=(unsigned char*)kate_malloc(size);
848   if (!kbitmap.bitmap->pixels) {
849     yyerror("Out of memory");
850     exit(-1);
851   }
852   kbitmap.bitmap->size=size;
853   n_bitmap_pixels=0;
854 }
855 
init_byte_stream(int nbytes)856 static void init_byte_stream(int nbytes)
857 {
858   if (nbytes<0) { yyerror("internal error: negative number of bytes"); exit(-1); }
859   byte_stream=(char*)kate_malloc(nbytes);
860   if (!byte_stream) {
861     yyerror("Out of memory");
862     exit(-1);
863   }
864   n_bytes_in_stream=0;
865   byte_stream_size=nbytes;
866 }
867 
set_color(kate_color * kc,uint32_t c)868 static void set_color(kate_color *kc,uint32_t c)
869 {
870   int r=(c>>24)&0xff;
871   int g=(c>>16)&0xff;
872   int b=(c>>8)&0xff;
873   int a=(c>>0)&0xff;
874   if (!kc) {
875     yyerror("Internal error: null color");
876     exit(-1);
877   }
878   if (r<0 || r>255) yyerrorf("red component (%d) must be between 0 and 255",r);
879   if (g<0 || g>255) yyerrorf("green component (%d) must be between 0 and 255",g);
880   if (b<0 || b>255) yyerrorf("blue component (%d) must be between 0 and 255",b);
881   if (a<0 || a>255) yyerrorf("alpha component (%d) must be between 0 and 255",a);
882   kc->r=r;
883   kc->g=g;
884   kc->b=b;
885   kc->a=a;
886 }
887 
init_event(kd_event * ev)888 static void init_event(kd_event *ev)
889 {
890   if (!ev) {
891     yyerror("Internal error: null event");
892     exit(-1);
893   }
894   ev->t0=ev->t1=ev->duration=(kate_float)-1.0;
895   ev->text=NULL;
896   ev->text_markup_type=kate_markup_none;
897   ev->region_index=ev->style_index=ev->secondary_style_index=-1;
898   ev->region=NULL;
899   ev->style=NULL;
900   ev->secondary_style=NULL;
901   ev->palette_index=ev->bitmap_index=-1;
902   ev->palette=NULL;
903   ev->bitmap=NULL;
904 }
905 
kd_encode_set_id(kate_state * kstate,unsigned int id)906 static void kd_encode_set_id(kate_state *kstate,unsigned int id)
907 {
908   if (id&0x80000000) yyerrorf("ID %d (hex %x) out of range, must fit on 31 bits",id,id);
909 
910   /* unused at the moment - will need to map an autogenerated id to this user id */
911   (void)kstate;
912   (void)id;
913 }
914 
add_entity(const char * entity,char ** text,size_t * wlen0)915 static int add_entity(const char *entity,char **text,size_t *wlen0)
916 {
917   int count=0;
918 
919   if (!entity || !text || !wlen0) {
920     yyerror("internal error: add_entity passed null parameter");
921     exit(-1);
922   }
923 
924   /* write out the entity */
925   while (*entity) {
926     int ret=kate_text_set_character(kate_utf8,*entity,text,wlen0);
927     if (ret<0) return ret;
928     count+=ret;
929     ++entity;
930   }
931   return count;
932 }
933 
expand_numeric_entities(const char * text)934 static char *expand_numeric_entities(const char *text)
935 {
936   enum {
937     s_text,
938     s_amp,
939     s_code,
940     s_named
941   } state=s_text;
942   int c,code=0,code_from_numeric,base=-1;
943   size_t len=strlen(text),len0=len+1,rlen0=len0,wlen0=len0,allocated=len0;
944   /* we might need to replace "&#00;" with "&amp;" - we can't use more characters, so we needn't allocate more */
945   /* this might change if we even can replace a numeric entity with a named one that is longer as a string */
946   char *newtext=(char*)kate_malloc(allocated),*newtextptr=newtext;
947 
948   if (!newtext) { yyerror("out of memory"); exit(-1); }
949 
950   while (1) {
951     int ret=kate_text_get_character(kate_utf8,&text,&rlen0);
952     if (ret<0) {
953       yyerrorf("failed to read character: %d",ret);
954       kate_free(newtext);
955       return NULL;
956     }
957     c=ret;
958 
959     code_from_numeric=0;
960     switch (state) {
961       case s_text:
962         if (c=='&') {
963           state=s_amp;
964           code=0;
965         }
966         break;
967       case s_amp:
968         if (c=='#') {
969           state=s_code;
970           base=-1; /* unknown yet */
971         }
972         else {
973           state=s_named;
974 
975           /* we've encountered a named entity, and we've discarded the & already,
976              so we need to add it now before the newly read character */
977           ret=kate_text_set_character(kate_utf8,'&',&newtextptr,&wlen0);
978           if (ret<0) {
979             yyerrorf("failed to write character: %d",ret);
980             kate_free(newtext);
981             return NULL;
982           }
983         }
984         break;
985       case s_code:
986         if (c==';') {
987           if (base<0) {
988             /* no code given */
989             yyerrorf("no code given in numeric entity");
990             c=0;
991             code_from_numeric=1;
992             state=s_text;
993           }
994           else {
995             c=code; /* this will be written below */
996             code_from_numeric=1;
997             state=s_text;
998           }
999         }
1000         else {
1001           /* if first character, determine if this is decimal or hexadecimal */
1002           if (base<0) {
1003             if (c=='x' || c=='X') {
1004               base=16;
1005               break; /* the code starts next character */
1006             }
1007             else {
1008               base=10;
1009               /* fall through */
1010             }
1011           }
1012 
1013           code*=base;
1014           if (isdigit(c)) code+=(c-'0');
1015           else if (base==16 && isxdigit(c)) code+=(tolower(c)-'a'+10);
1016           else yyerrorf("invalid character in numeric entity (only numeric entities are supported), got %d",c);
1017         }
1018         break;
1019       case s_named:
1020         if (c==';') {
1021           state=s_text;
1022         }
1023         break;
1024     }
1025 
1026     if (state==s_text || state==s_named) {
1027       /* we don't want to expand characters in "<&>" as they would then be wrongly interpreted,
1028          so we insert here as entities - note that we don't want to expand them and do another
1029          pass to reencode them, as we then might pick up others that *were* in the text verbatim */
1030       if (code_from_numeric && (c&~0xff)==0 && strchr("<&>",c)) {
1031         switch (c) {
1032           case '<': ret=add_entity("&lt;",&newtextptr,&wlen0); break;
1033           case '&': ret=add_entity("&amp;",&newtextptr,&wlen0); break;
1034           case '>': ret=add_entity("&gt;",&newtextptr,&wlen0); break;
1035         }
1036       }
1037       else {
1038         ret=kate_text_set_character(kate_utf8,c,&newtextptr,&wlen0);
1039       }
1040       if (ret<0) {
1041         yyerrorf("failed to write character: %d",ret);
1042         kate_free(newtext);
1043         return NULL;
1044       }
1045     }
1046     if (c==0) break;
1047   }
1048   return newtext;
1049 }
1050 
getrawline(const char ** text)1051 static char *getrawline(const char **text)
1052 {
1053   size_t rlen0;
1054   int newline,in_newline=0;
1055   const char *start_of_line;
1056   int c;
1057 
1058   if (!text || !*text) {
1059     yyerror("error: getrawline passed invalid text pointer");
1060     exit(-1);
1061   }
1062 
1063   rlen0=strlen(*text)+1;
1064   start_of_line=*text;
1065 
1066   while (1) {
1067     const char *ptr=*text;
1068     int ret=kate_text_get_character(kate_utf8,text,&rlen0);
1069     if (ret<0) {
1070       yyerrorf("failed to read character: %d",ret);
1071       return NULL;
1072     }
1073     c=ret;
1074     if (c==0) {
1075       /* end of the string, return everything */
1076       size_t len=strlen(start_of_line);
1077       char *line=(char*)kate_malloc(len+1);
1078       memcpy(line,start_of_line,len+1);
1079       *text=ptr; /* do not push past the start of the new line */
1080       return line;
1081     }
1082     newline=(c=='\r' || c=='\n');
1083     if (!newline && in_newline) {
1084       /* we are at the start of a new line */
1085       char *line=(char*)kate_malloc(ptr-start_of_line+1);
1086       memcpy(line,start_of_line,ptr-start_of_line);
1087       line[ptr-start_of_line]=0;
1088       *text=ptr; /* do not push past the start of the new line */
1089       return line;
1090     }
1091     in_newline=newline;
1092   }
1093 }
1094 
trimend(char * line,size_t rlen0,int * eol)1095 static void trimend(char *line,size_t rlen0,int *eol)
1096 {
1097   int ret;
1098   int c;
1099   int ws;
1100   char *text=line;
1101 
1102   if (!line) return;
1103 
1104   ret=kate_text_get_character(kate_utf8,(const char**)&text,&rlen0);
1105   if (ret<0) {
1106     yyerrorf("failed to read character: %d",ret);
1107     return;
1108   }
1109   c=ret;
1110   if (c==0) {
1111     *eol=1;
1112     return;
1113   }
1114 
1115   trimend(text,rlen0,eol);
1116 
1117   ws=((c<=0xff) && (strchr(" \t\n\r",c)!=NULL));
1118   if (*eol && ws) *line=0;
1119   if (!ws) *eol=0;
1120 }
1121 
trimline(const char * line)1122 static char *trimline(const char *line)
1123 {
1124   char *trimmed;
1125   size_t rlen0;
1126   int c;
1127   int eol=0;
1128 
1129   if (!line) {
1130     yyerror("error: trimline passed null line");
1131     exit(-1);
1132   }
1133 
1134   rlen0=strlen(line)+1;
1135 
1136   /* first seek to the first non whitespace character in the line */
1137   while (1) {
1138     const char *ptr=line;
1139     int ret=kate_text_get_character(kate_utf8,&ptr,&rlen0);
1140     if (ret<0) {
1141       yyerrorf("failed to read character: %d",ret);
1142       return NULL;
1143     }
1144     c=ret;
1145     if (!c || (c!=' ' && c!='\t')) {
1146       /* we found a non whitespace, or an end of line, stop */
1147       break;
1148     }
1149     /* we can advance the start of the line */
1150     line=ptr;
1151   }
1152 
1153   rlen0=strlen(line)+1;
1154   trimmed=(char*)kate_malloc(rlen0);
1155   memcpy(trimmed,line,rlen0);
1156   trimend(trimmed,strlen(trimmed)+1,&eol);
1157   return trimmed;
1158 }
1159 
trimtext(const char * text)1160 static char *trimtext(const char *text)
1161 {
1162   char *newtext=(char*)kate_malloc(1);
1163   *newtext=0;
1164   while (text && *text) {
1165     char *line=getrawline(&text);
1166     char *trimmed=trimline(line);
1167     kate_free(line);
1168     if (*trimmed && strcmp(trimmed,"\n")) {
1169       /* ignore empty lines */
1170       if (newtext && *newtext) {
1171         /* add a newline between lines (eg, not before the first line) */
1172         newtext=catstrings(newtext,"\n");
1173       }
1174       newtext=catstrings(newtext,trimmed);
1175     }
1176     kate_free(trimmed);
1177   }
1178   return newtext;
1179 }
1180 
trimtext_pre(const char * text)1181 static char *trimtext_pre(const char *text)
1182 {
1183   /* in pre, we just kill a new line at start and one at the end, if any */
1184   size_t len;
1185   char *newtext;
1186 
1187   if (!text) {
1188     yyerror("error: trimtext_pre passed null text");
1189     exit(-1);
1190   }
1191 
1192   len=strlen(text);
1193   newtext=(char*)kate_malloc(len+1);
1194 
1195   /* start */
1196   if (*text=='\n') {
1197     memcpy(newtext,text+1,len);
1198     --len;
1199   }
1200   else {
1201     memcpy(newtext,text,len+1);
1202   }
1203 
1204   /* end */
1205   if (len>0 && newtext[len-1]=='\n') {
1206     newtext[len-1]=0;
1207   }
1208 
1209   return newtext;
1210 }
1211 
backslash_n_to_newline(char * text)1212 static void backslash_n_to_newline(char *text)
1213 {
1214   char *ptr=text;
1215   while (ptr && (ptr=strstr(ptr,"\\n"))) {
1216     *ptr='\n';
1217     memmove(ptr+1,ptr+2,strlen(ptr+2)+1);
1218   }
1219 }
1220 
set_event_text(kd_event * ev,const char * text,int pre,int markup)1221 static void set_event_text(kd_event *ev,const char *text,int pre,int markup)
1222 {
1223   char *newtext,*expanded;
1224   size_t len;
1225 
1226   if (ev->text) {
1227     yyerrorf("text already set (to %s, trying to set to %s)",ev->text,text);
1228     return;
1229   }
1230   if (!text) {
1231     yyerror("null text");
1232     return;
1233   }
1234 
1235   len=strlen(text);
1236   newtext=(char*)kate_malloc(len+1);
1237   memcpy(newtext,text,len+1);
1238   backslash_n_to_newline(newtext);
1239 
1240   expanded=expand_numeric_entities(newtext);
1241   kate_free(newtext);
1242   newtext=expanded;
1243 
1244   if (!pre) {
1245     char *trimmed_newtext=trimtext(newtext);
1246     kate_free(newtext);
1247     newtext=trimmed_newtext;
1248   }
1249   else {
1250     char *trimmed_newtext=trimtext_pre(newtext);
1251     kate_free(newtext);
1252     newtext=trimmed_newtext;
1253   }
1254 
1255   if (markup) {
1256     ev->text_markup_type=kate_markup_simple;
1257   }
1258   else {
1259     ev->text_markup_type=kate_markup_none;
1260   }
1261 
1262   ev->text=newtext;
1263 }
1264 
set_event_text_from(kd_event * ev,const char * source,int pre,int markup)1265 static void set_event_text_from(kd_event *ev,const char *source,int pre,int markup)
1266 {
1267   FILE *f;
1268   char *text=NULL;
1269   char s[4096],*sret;
1270 
1271   f=fopen(source,"rt");
1272   if (!f) {
1273     yyerrorf("Failed to open file %s\n",source);
1274     exit(-1);
1275   }
1276   sret=fgets(s,sizeof(s),f);
1277   if (!sret) {
1278     yyerrorf("Failed to read from file %s\n",source);
1279     exit(-1);
1280   }
1281   while (!feof(f)) {
1282     /* This implicitely forbids embedded zeros - could this be a problem ? */
1283     text=catstrings(text,s);
1284     sret=fgets(s,sizeof(s),f);
1285     if (!sret) {
1286       yyerrorf("Failed to read from file %s\n",source);
1287       exit(-1);
1288     }
1289   }
1290   fclose(f);
1291 
1292   if (text) {
1293     set_event_text(ev,text,pre,markup);
1294     kate_free(text);
1295   }
1296 }
1297 
set_event_t0_t1(kd_event * ev,kate_float t0,kate_float t1)1298 static void set_event_t0_t1(kd_event *ev,kate_float t0,kate_float t1)
1299 {
1300   if (ev->t0>=0) { yyerror("start time already set"); return; }
1301   if (ev->t1>=0) { yyerror("end time already set"); return; }
1302   ev->t0=t0;
1303   ev->t1=t1;
1304 }
1305 
set_event_t0(kd_event * ev,kate_float v)1306 static void set_event_t0(kd_event *ev,kate_float v)
1307 {
1308   if (ev->t0>=0) { yyerror("start time already set"); return; }
1309   ev->t0=v;
1310 }
1311 
set_event_t1(kd_event * ev,kate_float v)1312 static void set_event_t1(kd_event *ev,kate_float v)
1313 {
1314   if (ev->t1>=0) { yyerror("end time already set"); return; }
1315   ev->t1=v;
1316 }
1317 
set_event_duration(kd_event * ev,kate_float v)1318 static void set_event_duration(kd_event *ev,kate_float v)
1319 {
1320   if (ev->duration>=0) { yyerror("duration already set"); return; }
1321   ev->duration=v;
1322 }
1323 
set_event_region_index(kd_event * ev,int r)1324 static void set_event_region_index(kd_event *ev,int r)
1325 {
1326   int ret;
1327   if (ev->region_index>=0 || ev->region) { yyerror("region already set"); return; }
1328   ev->region_index=r;
1329   ret=kate_encode_set_region_index(&k,r);
1330   if (ret<0) yyerrorf("failed to set region index: %d",ret);
1331 }
1332 
set_event_region(kd_event * ev,kate_region * kr)1333 static void set_event_region(kd_event *ev,kate_region *kr)
1334 {
1335   int ret;
1336   check_region(kr);
1337   if (ev->region_index>=0 || ev->region) { yyerror("region already set"); return; }
1338   ev->region=kr;
1339   ret=kate_encode_set_region(&k,kr);
1340   if (ret<0) yyerrorf("failed to set region: %d",ret);
1341 }
1342 
set_event_style_index(kd_event * ev,int s)1343 static void set_event_style_index(kd_event *ev,int s)
1344 {
1345   int ret;
1346   if (ev->style_index>=0 || ev->style) { yyerror("style already set"); return; }
1347   ev->style_index=s;
1348   ret=kate_encode_set_style_index(&k,s);
1349   if (ret<0) yyerrorf("failed to set style index: %d",ret);
1350 }
1351 
set_event_secondary_style_index(kd_event * ev,int s)1352 static void set_event_secondary_style_index(kd_event *ev,int s)
1353 {
1354   int ret;
1355   if (ev->secondary_style_index>=0 || ev->secondary_style) { yyerror("secondary style already set"); return; }
1356   ev->secondary_style_index=s;
1357   ret=kate_encode_set_secondary_style_index(&k,s);
1358   if (ret<0) yyerrorf("failed to set secondary style index: %d",ret);
1359 }
1360 
set_event_style(kd_event * ev,kate_style * ks)1361 static void set_event_style(kd_event *ev,kate_style *ks)
1362 {
1363   int ret;
1364   check_style(ks);
1365   if (ev->style_index>=0 || ev->style) { yyerror("style already set"); return; }
1366   ev->style=ks;
1367   ret=kate_encode_set_style(&k,ks);
1368   if (ret<0) yyerrorf("failed to set style: %d",ret);
1369 }
1370 
set_event_secondary_style(kd_event * ev,kate_style * ks)1371 static void set_event_secondary_style(kd_event *ev,kate_style *ks)
1372 {
1373   int ret;
1374   check_style(ks);
1375   if (ev->secondary_style_index>=0 || ev->secondary_style) { yyerror("secondary style already set"); return; }
1376   ev->secondary_style=ks;
1377   ret=kate_encode_set_secondary_style(&k,ks);
1378   if (ret<0) yyerrorf("failed to set secondary style: %d",ret);
1379 }
1380 
set_event_palette_index(kd_event * ev,int p)1381 static void set_event_palette_index(kd_event *ev,int p)
1382 {
1383   int ret;
1384   if (ev->palette_index>=0 || ev->palette) { yyerror("palette already set"); return; }
1385   ev->palette_index=p;
1386   ret=kate_encode_set_palette_index(&k,p);
1387   if (ret<0) yyerrorf("failed to set palette index: %d",ret);
1388 }
1389 
set_event_palette(kd_event * ev,kate_palette * kp)1390 static void set_event_palette(kd_event *ev,kate_palette *kp)
1391 {
1392   int ret;
1393   check_palette(kp);
1394   if (ev->palette_index>=0 || ev->palette) { yyerror("palette already set"); return; }
1395   ev->palette=kp;
1396   ret=kate_encode_set_palette(&k,kp);
1397   if (ret<0) yyerrorf("failed to set palette: %d",ret);
1398 }
1399 
set_event_bitmap_index(kd_event * ev,int b)1400 static void set_event_bitmap_index(kd_event *ev,int b)
1401 {
1402   int ret;
1403   if (ev->bitmap_index>=0 || ev->bitmap) { yyerror("bitmap already set"); return; }
1404   ev->bitmap_index=b;
1405   ret=kate_encode_set_bitmap_index(&k,b);
1406   if (ret<0) yyerrorf("failed to set bitmap index: %d",ret);
1407 }
1408 
set_event_bitmap(kd_event * ev,kate_bitmap * kb)1409 static void set_event_bitmap(kd_event *ev,kate_bitmap *kb)
1410 {
1411   int ret;
1412   check_bitmap(kb);
1413   if (ev->bitmap_index>=0 || ev->bitmap) { yyerror("bitmap already set"); return; }
1414   ev->bitmap=kb;
1415   ret=kate_encode_set_bitmap(&k,kb);
1416   if (ret<0) yyerrorf("failed to set bitmap: %d",ret);
1417 }
1418 
kd_add_event_meta(const char * tag,const char * value)1419 static void kd_add_event_meta(const char *tag,const char *value)
1420 {
1421   kate_meta *meta;
1422   int ret;
1423 
1424   ret=kate_meta_create(&meta);
1425   if (ret>=0) {
1426     ret=kate_meta_add_string(meta,tag,value);
1427     if (ret>=0) {
1428       ret=kate_encode_merge_meta(&k,meta);
1429       if (ret<0) {
1430         kate_meta_destroy(meta);
1431       }
1432     }
1433     else {
1434       kate_meta_destroy(meta);
1435     }
1436   }
1437   if (ret<0) yyerrorf("failed to add metadata: %d",ret);
1438 }
1439 
kd_add_event_meta_byte_stream(const char * tag)1440 static void kd_add_event_meta_byte_stream(const char *tag)
1441 {
1442   kate_meta *meta;
1443   int ret;
1444 
1445   ret=kate_meta_create(&meta);
1446   if (ret>=0) {
1447     ret=kate_meta_add(meta,tag,byte_stream,byte_stream_size);
1448     if (ret>=0) {
1449       ret=kate_encode_merge_meta(&k,meta);
1450       if (ret<0) {
1451         kate_meta_destroy(meta);
1452       }
1453     }
1454     else {
1455       kate_meta_destroy(meta);
1456     }
1457   }
1458   if (ret<0) yyerrorf("failed to add metadata: %d",ret);
1459 
1460   kate_free(byte_stream);
1461   byte_stream=NULL;
1462   n_bytes_in_stream=0;
1463   byte_stream_size=0;
1464 }
1465 
check_event(kd_event * ev)1466 static kd_event *check_event(kd_event *ev)
1467 {
1468   /* we can set:
1469      start and end
1470      start and duration
1471      duration and end
1472      */
1473   int sets=0;
1474   if (ev->t0>=(kate_float)0.0) ++sets;
1475   if (ev->t1>=(kate_float)0.0) ++sets;
1476   if (ev->duration>=(kate_float)0.0) ++sets;
1477   if (sets<2) { yyerror("start/end times underspecified"); return NULL; }
1478   if (sets>2) { yyerror("start/end times overspecified"); return NULL; }
1479 
1480   if (ev->t0<(kate_float)0.0) ev->t0=ev->t1-ev->duration;
1481   if (ev->t1<(kate_float)0.0) ev->t1=ev->t0+ev->duration;
1482 
1483   return ev;
1484 }
1485 
init_motion(void)1486 static void init_motion(void)
1487 {
1488   kmotions=(kd_motion*)kate_realloc(kmotions,(nkmotions+1)*sizeof(kd_motion));
1489   if (!kmotions) { yyerror("out of memory"); exit(-1); }
1490   ++nkmotions;
1491   kmotions[nkmotions-1].idx=0;
1492   kmotions[nkmotions-1].motion=kate_malloc(sizeof(kate_motion));
1493   kmotion=kmotions[nkmotions-1].motion;
1494   if (!kmotion) { yyerror("out of memory"); exit(-1); }
1495 
1496   if (kate_motion_init(kmotion)<0) {
1497     yyerror("failed to init motion");
1498     exit(-1);
1499   }
1500   kmotion->semantics=(kate_motion_semantics)-1;
1501 }
1502 
add_curve_to_motion(kate_motion * kmotion,kate_float duration)1503 static void add_curve_to_motion(kate_motion *kmotion,kate_float duration)
1504 {
1505   kmotion->ncurves++;
1506   kmotion->curves=(kate_curve**)kate_realloc(kmotion->curves,kmotion->ncurves*sizeof(kate_curve*));
1507   if (!kmotion->curves) { yyerror("out of memory"); exit(-1); }
1508   kmotion->durations=(kate_float*)kate_realloc(kmotion->durations,kmotion->ncurves*sizeof(kate_float));
1509   if (!kmotion->durations) { yyerror("out of memory"); exit(-1); }
1510 
1511   if (kcurve.curve) {
1512     check_curve(kcurve.curve);
1513     kmotion->curves[kmotion->ncurves-1]=kcurve.curve;
1514     kcurve.curve=NULL;
1515   }
1516   else {
1517     if (kcurve.idx>=ki.ncurves) {
1518       yyerror("Internal error: curve index out of range");
1519       exit(-1);
1520     }
1521     kmotion->curves[kmotion->ncurves-1]=ki.curves[kcurve.idx];
1522   }
1523 
1524   kmotion->durations[kmotion->ncurves-1]=duration;
1525 }
1526 
get_num_glyphs(const char * text)1527 static size_t get_num_glyphs(const char *text)
1528 {
1529   size_t len0;
1530   size_t nglyphs=0;
1531   int intag=0,c;
1532 
1533   if (!text) { yyerror("Internal error: get_num_glyphs got NULL text"); exit(-1); }
1534 
1535   len0=strlen(text)+1;
1536   while ((c=kate_text_get_character(kate_utf8,&text,&len0))>0) {
1537     if (c=='<') intag++;
1538     if (!intag) ++nglyphs;
1539     if (c=='>') intag--;
1540   }
1541   return nglyphs;
1542 }
1543 
init_simple_glyph_pointer_motion(void)1544 static void init_simple_glyph_pointer_motion(void)
1545 {
1546   init_motion();
1547   kmotion->semantics=kate_motion_semantics_glyph_pointer_1;
1548   karaoke_base_height=(kate_float)0;
1549   karaoke_top_height=(kate_float)0;
1550 }
1551 
get_glyph_pointer_offset(unsigned int pointer_id)1552 static int get_glyph_pointer_offset(unsigned int pointer_id)
1553 {
1554   if (pointer_id<1 || pointer_id>4) {
1555     yyerrorf("Only glyph pointers 1-4 are available (trying to set %d)",pointer_id);
1556     exit(-1);
1557   }
1558   return (kate_motion_semantics)(kate_motion_semantics_glyph_pointer_1+pointer_id-1);
1559 }
1560 
get_last_glyph_x(const kate_motion * km)1561 static kate_float get_last_glyph_x(const kate_motion *km)
1562 {
1563   const kate_curve *kc;
1564   if (!km) { yyerror("internal error: no motion"); exit(-1); }
1565   if (km->ncurves==0) return (kate_float)-0.5; /* by default, center of the glyph before the first one (eg, marks nothing yet) */
1566   kc=km->curves[km->ncurves-1];
1567   if (kc->npts<1) yyerror("internal error: no points in last curve");
1568   return kc->pts[kc->npts*2-2]; /* -1 would be y */
1569 }
1570 
compute_karaoke_height(float y)1571 static kate_float compute_karaoke_height(float y)
1572 {
1573   /* turn height (bottom to top) to screen coordinates (top to bottom): negate */
1574   return -(karaoke_base_height*(1-y)+karaoke_top_height*y);
1575 }
1576 
add_glyph_pause(kate_float dt,kate_float y)1577 static void add_glyph_pause(kate_float dt,kate_float y)
1578 {
1579   init_curve();
1580   kcurve.curve->type=kate_curve_static;
1581   kcurve.curve->npts=1;
1582   kcurve.curve->pts=(kate_float*)kate_malloc(kcurve.curve->npts*2*sizeof(kate_float));
1583   if (!kcurve.curve->pts) { yyerror("out of memory"); exit(-1); }
1584   kcurve.curve->pts[0]=get_last_glyph_x(kmotion);
1585   kcurve.curve->pts[1]=compute_karaoke_height(y);
1586   add_curve_to_motion(kmotion,dt);
1587 }
1588 
add_glyph_transition(unsigned int glyph,kate_float dt,kate_float ystart,kate_float ytop,int absolute,kate_float pause_fraction)1589 static void add_glyph_transition(unsigned int glyph,kate_float dt,kate_float ystart,kate_float ytop,int absolute,kate_float pause_fraction)
1590 {
1591   /* get the last glyph position and the new one */
1592   kate_float x0=get_last_glyph_x(kmotion);
1593   kate_float x1=glyph+(kate_float)0.5;
1594   size_t n;
1595 
1596   /* convert absolute to relative */
1597   if (absolute) {
1598     for (n=0;n<kmotion->ncurves;++n) dt-=kmotion->durations[n];
1599   }
1600 
1601   if (dt<(kate_float)0.0) {
1602     yyerrorf("duration (%f) must not be negative\n",dt);
1603     exit(-1);
1604   }
1605 
1606   /* add a pause before the next jump */
1607   if (pause_fraction>(kate_float)0.0) {
1608     kate_float delay=dt*pause_fraction;
1609     add_glyph_pause(delay,ystart);
1610     dt-=delay;
1611     if (dt<(kate_float)0.0) dt=(kate_float)0.0;
1612     x0=get_last_glyph_x(kmotion);
1613   }
1614 
1615   init_curve();
1616 
1617   if (dt==(kate_float)0.0) {
1618     /* if zero duration, just add static point at the end point */
1619     kcurve.curve->type=kate_curve_static;
1620     kcurve.curve->npts=1;
1621     kcurve.curve->pts=(kate_float*)kate_malloc(kcurve.curve->npts*2*sizeof(kate_float));
1622     if (!kcurve.curve->pts) { yyerror("out of memory"); exit(-1); }
1623     /* directly at the end position */
1624     kcurve.curve->pts[0]=x1;
1625     kcurve.curve->pts[1]=compute_karaoke_height(ystart);
1626   }
1627   else {
1628     kcurve.curve->type=kate_curve_catmull_rom_spline;
1629     kcurve.curve->npts=3+2; /* the two end points are duplicated */
1630     kcurve.curve->pts=(kate_float*)kate_malloc(kcurve.curve->npts*2*sizeof(kate_float));
1631     if (!kcurve.curve->pts) { yyerror("out of memory"); exit(-1); }
1632 
1633     /* start position */
1634     kcurve.curve->pts[0]=kcurve.curve->pts[2]=x0;
1635     kcurve.curve->pts[1]=kcurve.curve->pts[3]=compute_karaoke_height(ystart);
1636 
1637     /* the interpolated points */
1638     for (n=2;n<kcurve.curve->npts-2;++n) {
1639       kate_float t=(n-1)/(kate_float)(kcurve.curve->npts-2-1);
1640       kcurve.curve->pts[n*2]=kcurve.curve->pts[n*2+2]=x1*t+x0*((kate_float)1.0-t);
1641       kcurve.curve->pts[n*2+1]=kcurve.curve->pts[n*2+3]=compute_karaoke_height(ytop);
1642     }
1643 
1644     /* end position */
1645     kcurve.curve->pts[kcurve.curve->npts*2-4]=kcurve.curve->pts[kcurve.curve->npts*2-2]=x1;
1646     kcurve.curve->pts[kcurve.curve->npts*2-3]=kcurve.curve->pts[kcurve.curve->npts*2-1]=compute_karaoke_height(ystart);
1647   }
1648 
1649   add_curve_to_motion(kmotion,dt);
1650 }
1651 
add_glyph_transition_to_text(const char * text,kate_float dt,kate_float ystart,kate_float ytop,int absolute,kate_float pause_fraction)1652 static void add_glyph_transition_to_text(const char *text,kate_float dt,kate_float ystart,kate_float ytop,int absolute,kate_float pause_fraction)
1653 {
1654   char *newtext;
1655 
1656   if (!text) {
1657     yyerror("null text");
1658     return;
1659   }
1660 
1661   if (kevent.text) {
1662     char *text2=(char*)kate_realloc(kevent.text,strlen(kevent.text)+strlen(text)+1);
1663     if (!text2) {
1664       yyerror("out of memory");
1665       return;
1666     }
1667     strcat(text2,text);
1668     kevent.text=text2;
1669   }
1670   else {
1671     char *text2=(char*)kate_malloc(strlen(text)+1);
1672     if (!text2) {
1673       yyerror("out of memory");
1674       return;
1675     }
1676     strcpy(text2,text);
1677     kevent.text=text2;
1678   }
1679 
1680   backslash_n_to_newline(kevent.text);
1681   newtext=expand_numeric_entities(kevent.text);
1682   if (!newtext) return;
1683   kate_free(kevent.text);
1684   kevent.text=newtext;
1685 
1686   add_glyph_transition(get_num_glyphs(kevent.text)-1,dt,ystart,ytop,absolute,pause_fraction);
1687 }
1688 
set_style_morph(kd_event * ev,int from,int to)1689 static void set_style_morph(kd_event *ev,int from,int to)
1690 {
1691   int ret;
1692 
1693   if (!ev) {
1694     yyerror("internal error: no event");
1695     exit(-1);
1696   }
1697   if (from<0 || to<0) {
1698     yyerror("error: style index cannot be negative");
1699     exit(-1);
1700   }
1701 
1702   if (ev->style_index>=0 || ev->style) { yyerror("style already set"); return; }
1703   ev->style_index=from;
1704   ret=kate_encode_set_style_index(&k,from);
1705   if (ret<0) yyerrorf("failed to set style index: %d",ret);
1706 
1707   if (ev->secondary_style_index>=0 || ev->secondary_style) { yyerror("secondary style already set"); return; }
1708   ev->secondary_style_index=to;
1709   ret=kate_encode_set_secondary_style_index(&k,to);
1710   if (ret<0) yyerrorf("failed to set secondary_style index: %d",ret);
1711 }
1712 
clear_local_bitmaps(void)1713 static void clear_local_bitmaps(void)
1714 {
1715   size_t n;
1716 
1717   if (local_bitmap_names) {
1718     for (n=0;n<n_local_bitmaps;++n) {
1719       if (local_bitmap_names[n]) kate_free(local_bitmap_names[n]);
1720       if (local_bitmaps[n]) {
1721         if(local_bitmaps[n]->meta) kate_meta_destroy(local_bitmaps[n]->meta);
1722         kate_free(local_bitmaps[n]->pixels);
1723         kate_free(local_bitmaps[n]);
1724       }
1725     }
1726     kate_free(local_bitmap_names);
1727     local_bitmap_names=NULL;
1728     kate_free(local_bitmaps);
1729     local_bitmaps=NULL;
1730   }
1731   n_local_bitmaps=0;
1732 }
1733 
clear_event(kd_event * ev)1734 static void clear_event(kd_event *ev)
1735 {
1736   if (!ev) {
1737     yyerror("internal error: no event");
1738     exit(-1);
1739   }
1740   if (ev->text) {
1741     kate_free(ev->text);
1742     ev->text=NULL;
1743   }
1744   clear_motions();
1745   clear_local_bitmaps();
1746 }
1747 
kd_finalize_simple_timed_glyph_motion(kate_motion * kmotion)1748 static void kd_finalize_simple_timed_glyph_motion(kate_motion *kmotion)
1749 {
1750   const kd_event *ev=&kevent;
1751   kate_float duration=ev->duration;
1752   kate_float t0=ev->t0,t1=ev->t1;
1753   kate_float duration_so_far;
1754   size_t n;
1755   int sets;
1756 
1757   if (!kmotion) {
1758     yyerror("internal error: kd_finalize_simple_timed_glyph_motion passed NULL motion");
1759     exit(-1);
1760   }
1761 
1762   /* for this helper motion, we require the timing of the event to be known in advance */
1763   sets=0;
1764   if (t0>=(kate_float)0.0) ++sets;
1765   if (t1>=(kate_float)0.0) ++sets;
1766   if (duration>=(kate_float)0.0) ++sets;
1767   if (sets<2) { yyerror("start/end times must be specified before timed glyph marker motion setup"); return; }
1768   if (sets>2) { yyerror("start/end times overspecified"); return; }
1769 
1770   if (t0<(kate_float)0.0) t0=t1-duration;
1771   if (t1<(kate_float)0.0) t1=t0+duration;
1772   duration=t1-t0;
1773 
1774   /* add a pause to take us to the end time */
1775   duration_so_far=(kate_float)0.0;
1776   for (n=0;n<kmotion->ncurves;++n) duration_so_far+=kmotion->durations[n];
1777   if (duration_so_far>duration) {
1778     yyerrorf("Simple timed glyph motion lasts longer than its event (motion %f, event %f)",duration_so_far,duration);
1779     exit(-1);
1780   }
1781   add_glyph_pause(duration-duration_so_far,(kate_float)1.0);
1782 }
1783 
set_motion_mapping(kate_motion * kmotion,kate_motion_mapping x_mapping,kate_motion_mapping y_mapping)1784 static void set_motion_mapping(kate_motion *kmotion,kate_motion_mapping x_mapping,kate_motion_mapping y_mapping)
1785 {
1786   if (!kmotion) {
1787     yyerror("internal error: set_motion_mapping passed NULL motion");
1788     exit(-1);
1789   }
1790 
1791   kmotion->x_mapping=x_mapping;
1792   kmotion->y_mapping=y_mapping;
1793 }
1794 
set_motion_semantics(kate_motion * kmotion,kate_motion_semantics semantics)1795 static void set_motion_semantics(kate_motion *kmotion,kate_motion_semantics semantics)
1796 {
1797   if (!kmotion) {
1798     yyerror("internal error: set_motion_semantics passed NULL motion");
1799     exit(-1);
1800   }
1801 
1802   if (kmotion->semantics!=(kate_motion_semantics)-1) { yyerror("semantics is already defined"); return; }
1803   kmotion->semantics=semantics;
1804 }
1805 
kd_get_marker_position_semantics(int n)1806 static kate_motion_semantics kd_get_marker_position_semantics(int n)
1807 {
1808   switch (n) {
1809     case 1: return kate_motion_semantics_marker1_position;
1810     case 2: return kate_motion_semantics_marker2_position;
1811     case 3: return kate_motion_semantics_marker3_position;
1812     case 4: return kate_motion_semantics_marker4_position;
1813     default: yyerrorf("Invalid marker number: %d (only 1-4 are supported)",n); exit(-1);
1814   }
1815   return kate_motion_semantics_marker4_position;
1816 }
1817 
kd_get_marker_bitmap_semantics(int n)1818 static kate_motion_semantics kd_get_marker_bitmap_semantics(int n)
1819 {
1820   switch (n) {
1821     case 1: return kate_motion_semantics_marker1_bitmap;
1822     case 2: return kate_motion_semantics_marker2_bitmap;
1823     case 3: return kate_motion_semantics_marker3_bitmap;
1824     case 4: return kate_motion_semantics_marker4_bitmap;
1825     default: yyerrorf("Invalid marker number: %d (only 1-4 are supported)",n); exit(-1);
1826   }
1827   return kate_motion_semantics_marker4_bitmap;
1828 }
1829 
kd_get_glyph_pointer_semantics(int n)1830 static kate_motion_semantics kd_get_glyph_pointer_semantics(int n)
1831 {
1832   switch (n) {
1833     case 1: return kate_motion_semantics_glyph_pointer_1;
1834     case 2: return kate_motion_semantics_glyph_pointer_2;
1835     case 3: return kate_motion_semantics_glyph_pointer_3;
1836     case 4: return kate_motion_semantics_glyph_pointer_4;
1837     default: yyerrorf("Invalid glyph pointer number: %d (only 1-4 are supported)",n); exit(-1);
1838   }
1839   return kate_motion_semantics_glyph_pointer_4;
1840 }
1841 
kd_get_glyph_pointer_bitmap_semantics(int n)1842 static kate_motion_semantics kd_get_glyph_pointer_bitmap_semantics(int n)
1843 {
1844   switch (n) {
1845     case 1: return kate_motion_semantics_glyph_pointer_1_bitmap;
1846     case 2: return kate_motion_semantics_glyph_pointer_2_bitmap;
1847     case 3: return kate_motion_semantics_glyph_pointer_3_bitmap;
1848     case 4: return kate_motion_semantics_glyph_pointer_4_bitmap;
1849     default: yyerrorf("Invalid glyph pointer number: %d (only 1-4 are supported)",n); exit(-1);
1850   }
1851   return kate_motion_semantics_glyph_pointer_4_bitmap;
1852 }
1853 
kd_add_event_motion(kate_motion * kmotion)1854 static void kd_add_event_motion(kate_motion *kmotion)
1855 {
1856   int ret;
1857 
1858   if (!kmotion) {
1859     yyerror("internal error: kd_add_event_motion passed NULL motion");
1860     exit(-1);
1861   }
1862 
1863   check_motion(kmotion);
1864   ret=kate_encode_add_motion(&k,kmotion,1);
1865   if (ret<0) {
1866     yyerrorf("failed to add motion: %d",ret);
1867     exit(-1);
1868   }
1869   clear_motions();
1870 }
1871 
kd_add_event_motion_index(size_t idx)1872 static void kd_add_event_motion_index(size_t idx)
1873 {
1874   int ret;
1875 
1876   if (idx>=ki.nmotions) { yyerrorf("Motion index %u out of range (%u motions available)",idx,ki.nmotions); exit(-1); }
1877 
1878   ret=kate_encode_add_motion_index(&k,idx);
1879   if (ret<0) {
1880     yyerrorf("failed to add motion: %d",ret);
1881     exit(-1);
1882   }
1883   clear_motions();
1884 }
1885 
init_font_range(void)1886 static void init_font_range(void)
1887 {
1888   krange=(kate_font_range*)kate_malloc(sizeof(kate_font_range));
1889   if (!krange) { yyerror("out of memory"); exit(-1); }
1890   krange->first_code_point=-1;
1891   krange->last_code_point=-1;
1892   krange->first_bitmap=-1;
1893 }
1894 
set_font_range_code_point_string(int * cp,const char * s)1895 static void set_font_range_code_point_string(int *cp,const char *s)
1896 {
1897   size_t len0;
1898   int ret,c;
1899 
1900   if (!cp) { yyerror("internal error: no code point pointer"); exit(-1); }
1901   if (!s) { yyerror("internal error: no string"); exit(-1); }
1902   len0=strlen(s)+1;
1903   ret=kate_text_get_character(kate_utf8,&s,&len0);
1904   if (ret<0) {
1905     yyerrorf("failed to get character from string: %d",ret);
1906     return;
1907   }
1908   c=ret;
1909   ret=kate_text_get_character(kate_utf8,&s,&len0);
1910   if (ret<0) {
1911     yyerrorf("failed to get character from string: %d",ret);
1912     return;
1913   }
1914   if (ret) {
1915     yyerror("code point string should contain only one character");
1916     return;
1917   }
1918   *cp=c;
1919 }
1920 
set_font_range_first_code_point_string(const char * s)1921 static void set_font_range_first_code_point_string(const char *s)
1922 {
1923   if (!s) { yyerror("internal error: no string"); exit(-1); }
1924   if (!krange) { yyerror("internal error: no font range"); exit(-1); }
1925   set_font_range_code_point_string(&krange->first_code_point,s);
1926 }
1927 
set_font_range_last_code_point_string(const char * s)1928 static void set_font_range_last_code_point_string(const char *s)
1929 {
1930   if (!s) { yyerror("internal error: no string"); exit(-1); }
1931   if (!krange) { yyerror("internal error: no font range"); exit(-1); }
1932   set_font_range_code_point_string(&krange->last_code_point,s);
1933 }
1934 
set_font_range_first_code_point(int idx)1935 static void set_font_range_first_code_point(int idx)
1936 {
1937   if (!krange) { yyerror("internal error: no font range"); exit(-1); }
1938   krange->first_code_point=idx;
1939 }
1940 
set_font_range_last_code_point(int idx)1941 static void set_font_range_last_code_point(int idx)
1942 {
1943   if (!krange) { yyerror("internal error: no font range"); exit(-1); }
1944   krange->last_code_point=idx;
1945 }
1946 
set_font_range_first_bitmap(int idx)1947 static void set_font_range_first_bitmap(int idx)
1948 {
1949   if (!krange) { yyerror("internal error: no font range"); exit(-1); }
1950   krange->first_bitmap=idx;
1951 }
1952 
add_font_range(kate_info * ki,const char * name,kate_font_range * kfr)1953 static void add_font_range(kate_info *ki,const char *name,kate_font_range *kfr)
1954 {
1955   int ret;
1956   if (!ki || !kfr) { yyerror("internal error: no kate_info or kate_font_range"); exit(-1); }
1957   if (!krange) { yyerror("internal error: no font range"); exit(-1); }
1958   if (krange->first_code_point<0) yyerror("first code point not set");
1959   if (krange->last_code_point<0) yyerror("last code point not set");
1960   if (krange->last_code_point<krange->first_code_point) yyerror("last code point cannnot be less than first code point");
1961   if (krange->first_bitmap<0) yyerror("bitmap index not set");
1962   ret=kate_info_add_font_range(ki,kfr);
1963   if (ret<0) {
1964     yyerrorf("failed to add font range: %d",ret);
1965   }
1966   else {
1967     font_range_names=(char**)kate_realloc(font_range_names,ki->nfont_ranges*sizeof(char*));
1968     if (!font_range_names) {
1969       yyerror("Out of memory");
1970       exit(-1);
1971     }
1972     font_range_names[ki->nfont_ranges-1]=name?dupstring(name):NULL;
1973   }
1974 }
1975 
find_font_range(const kate_info * ki,const char * name)1976 static int find_font_range(const kate_info *ki,const char *name)
1977 {
1978   return find_item(name,ki->nfont_ranges,font_range_names);
1979 }
1980 
init_font_mapping(void)1981 static void init_font_mapping(void)
1982 {
1983   kmapping=(kate_font_mapping*)kate_malloc(sizeof(kate_font_mapping));
1984   if (!kmapping) { yyerror("out of memory"); exit(-1); }
1985   kmapping->nranges=0;
1986   kmapping->ranges=NULL;
1987 }
1988 
check_font_overlap(const kate_font_range * kfr0,const kate_font_range * kfr1)1989 static int check_font_overlap(const kate_font_range *kfr0,const kate_font_range *kfr1)
1990 {
1991   if (!kfr0 || !kfr1) return KATE_E_INVALID_PARAMETER;
1992 
1993   if (kfr0->last_code_point<kfr1->first_code_point) return 0;
1994   if (kfr1->last_code_point<kfr0->first_code_point) return 0;
1995 
1996   return KATE_E_INIT;
1997 }
1998 
check_font_ranges(const kate_font_mapping * kfm)1999 static int check_font_ranges(const kate_font_mapping *kfm)
2000 {
2001   size_t n,l;
2002 
2003   if (!kfm) return KATE_E_INVALID_PARAMETER;
2004 
2005   for (n=0;n<kfm->nranges;++n) {
2006     const kate_font_range *kfr=kfm->ranges[n];
2007     if (!kfr) return KATE_E_INIT;
2008     if (kfr->last_code_point<kfr->first_code_point) return KATE_E_INIT;
2009     for (l=n+1;l<kfm->nranges;++l) {
2010       int ret=check_font_overlap(kfr,kfm->ranges[l]);
2011       if (ret<0) return ret;
2012     }
2013   }
2014 
2015   return 0;
2016 }
2017 
add_font_range_to_mapping(void)2018 static void add_font_range_to_mapping(void)
2019 {
2020   int ret;
2021 
2022   if (!krange) { yyerror("internal error: no font range"); exit(-1); }
2023   if (!kmapping) { yyerror("internal error: no font mapping"); exit(-1); }
2024 
2025   kmapping->ranges=(kate_font_range**)kate_realloc(kmapping->ranges,(kmapping->nranges+1)*sizeof(kate_font_range*));
2026   if (!kmapping->ranges) {
2027     yyerror("error: out of memory");
2028     exit(-1);
2029   }
2030   kmapping->ranges[kmapping->nranges]=krange;
2031   ++kmapping->nranges;
2032 
2033   ret=check_font_ranges(kmapping);
2034   if (ret<0) yyerror("font mapping ranges overlap");
2035 
2036   krange=NULL;
2037 }
2038 
add_font_mapping(kate_info * ki,const char * name,kate_font_mapping * kfm)2039 static void add_font_mapping(kate_info *ki,const char *name,kate_font_mapping *kfm)
2040 {
2041   int ret;
2042   if (!ki) { yyerror("internal error: no kate_info"); exit(-1); }
2043   if (!kfm) { yyerror("internal error: no font mapping"); exit(-1); }
2044   if (kfm->nranges==0) yyerror("font mapping has no ranges");
2045   ret=kate_info_add_font_mapping(ki,kfm);
2046   if (ret<0) {
2047     yyerrorf("failed to add font mapping: %d",ret);
2048   }
2049   else {
2050     font_mapping_names=(char**)kate_realloc(font_mapping_names,ki->nfont_mappings*sizeof(char*));
2051     if (!font_mapping_names) {
2052       yyerror("Out of memory");
2053       exit(-1);
2054     }
2055     font_mapping_names[ki->nfont_mappings-1]=name?dupstring(name):NULL;
2056   }
2057 }
2058 
find_font_mapping(const kate_info * ki,const char * name)2059 static int find_font_mapping(const kate_info *ki,const char *name)
2060 {
2061   return find_item(name,ki->nfont_mappings,font_mapping_names);
2062 }
2063 
kd_write_headers(void)2064 static void kd_write_headers(void)
2065 {
2066   int ret=write_headers(katedesc_out);
2067   if (ret<0) {
2068     yyerrorf("Failed to write headers: %d\n",ret);
2069     exit(-1);
2070   }
2071 }
2072 
kd_encode_text(kate_state * kstate,kd_event * ev)2073 static void kd_encode_text(kate_state *kstate,kd_event *ev)
2074 {
2075   int ret;
2076   ogg_packet op;
2077 
2078   if (!ev) { yyerror("internal error: no event"); exit(-1); }
2079   ret=kate_encode_set_markup_type(kstate,ev->text_markup_type);
2080   if (ret<0) {
2081     yyerrorf("failed to set text markup type: %d",ret);
2082     return;
2083   }
2084   update_stream_time(kstate,katedesc_out,kate_duration_granule(kstate->ki,timebase+ev->t0));
2085   ret=kate_ogg_encode_text(kstate,timebase+ev->t0,timebase+ev->t1,ev->text?ev->text:"",ev->text?strlen(ev->text):0,&op);
2086   if (ret<0) {
2087     yyerrorf("failed to encode text %s: %d",ev->text?ev->text:"<none>",ret);
2088     return;
2089   }
2090   ret=send_packet(katedesc_out,&op,kate_duration_granule(kstate->ki,timebase+ev->t0));
2091   if (ret<0) {
2092     yyerrorf("failed to send text packet: %d",ret);
2093   }
2094 }
2095 
kd_encode_set_language(kate_state * kstate,const char * s)2096 static void kd_encode_set_language(kate_state *kstate,const char *s)
2097 {
2098   int ret;
2099   if (!s) { yyerror("internal error: no language string"); exit(-1); }
2100   ret=kate_encode_set_language(kstate,s);
2101   if (ret<0) yyerrorf("failed to set event language override: %d",ret);
2102 }
2103 
make_color(uint32_t r,uint32_t g,uint32_t b,uint32_t a)2104 static uint32_t make_color(uint32_t r,uint32_t g,uint32_t b,uint32_t a)
2105 {
2106   return (r<<24)|(g<<16)|(b<<8)|a;
2107 }
2108 
make_color_alpha(uint32_t c,uint32_t a)2109 static uint32_t make_color_alpha(uint32_t c,uint32_t a)
2110 {
2111   return (c&0xffffff00)|a;
2112 }
2113 
record_macro_name(const char * name)2114 static void record_macro_name(const char *name)
2115 {
2116   size_t len;
2117   if (!name) { yyerror("internal error: no macro name"); exit(-1); }
2118   len=strlen(name);
2119   if (temp_macro_name) kate_free(temp_macro_name);
2120   temp_macro_name=kate_malloc(len+1);
2121   if (!temp_macro_name) { yyerror("out of memory"); exit(-1); }
2122   strcpy(temp_macro_name,name);
2123 }
2124 
add_temp_macro(const char * body)2125 static void add_temp_macro(const char *body)
2126 {
2127   if (!body) { yyerror("internal error: no macro body"); exit(-1); }
2128   if (!temp_macro_name) { yyerror("internal error - unknown macro name"); return; }
2129   add_macro(temp_macro_name,body);
2130   kate_free(temp_macro_name);
2131   temp_macro_name=NULL;
2132 }
2133 
set_granule_rate(unsigned int numerator,unsigned int denominator)2134 static void set_granule_rate(unsigned int numerator,unsigned int denominator)
2135 {
2136   ki.gps_numerator=numerator;
2137   ki.gps_denominator=denominator;
2138 }
2139 
set_granule_shift(unsigned int granule_shift)2140 static void set_granule_shift(unsigned int granule_shift)
2141 {
2142   if (granule_shift>=64) yyerror("granule shift out of range (0-64)\n");
2143   ki.granule_shift=granule_shift;
2144 }
2145 
set_canvas_size(unsigned int width,unsigned int height)2146 static void set_canvas_size(unsigned int width,unsigned int height)
2147 {
2148   int ret=kate_info_set_original_canvas_size(&ki,width,height);
2149   if (ret<0) {
2150     yyerror("failed to set original canvas size");
2151     exit(-1);
2152   }
2153 }
2154 
add_comment(kate_comment * kc,const char * s)2155 static void add_comment(kate_comment *kc,const char *s)
2156 {
2157   /* check for "ENCODER=," as kateenc now sets it and we don't want cycles
2158      of decode/encode to duplicate them, and we want the new one to replace
2159      any existing one */
2160   int different=0;
2161   const char *encoder="ENCODER=",*sptr=s;
2162   while (*encoder) if ((*encoder++|32)!=(*sptr++|32)) {
2163     different=1;
2164     break;
2165   }
2166   if (different) {
2167     CHECK_KATE_API_ERROR(kate_comment_add(kc,s));
2168   }
2169 }
2170 
cleanup_names(char ** names,size_t count)2171 static void cleanup_names(char **names,size_t count)
2172 {
2173   size_t n;
2174   if (names) {
2175     for (n=0;n<count;++n) if (names[n]) kate_free(names[n]);
2176     kate_free(names);
2177   }
2178 }
2179 
cleanup_memory(void)2180 static void cleanup_memory(void)
2181 {
2182   cleanup_names(style_names,ki.nstyles);
2183   cleanup_names(region_names,ki.nregions);
2184   cleanup_names(curve_names,ki.ncurves);
2185   cleanup_names(motion_names,ki.nmotions);
2186   cleanup_names(bitmap_names,ki.nbitmaps);
2187   cleanup_names(palette_names,ki.npalettes);
2188   cleanup_names(font_range_names,ki.nfont_ranges);
2189   cleanup_names(font_mapping_names,ki.nfont_mappings);
2190   cleanup_names(local_bitmap_names,n_local_bitmaps);
2191 
2192   free_macros();
2193 }
2194 
2195 
2196 %}
2197 
2198 %pure_parser
2199 
2200 %union {
2201   int number;
2202   unsigned int unumber;
2203   kate_float fp;
2204   const char *string;
2205   char *dynstring;
2206   kate_style *style;
2207   kate_region *region;
2208   kate_curve *curve;
2209   uint32_t color;
2210 }
2211 
2212 %token <number> KATE
2213 %token <number> DEFS
2214 %token <number> LANGUAGE COMMENT CATEGORY
2215 %token <number> DEFINE MACRO STYLE REGION CURVE
2216 %token <number> TEXT BACKGROUND COLOR POSITION SIZE DEFAULT METRIC
2217 %token <number> HALIGN VALIGN HLEFT HCENTER HRIGHT VTOP VCENTER VBOTTOM
2218 %token <number> POINTS
2219 %token <number> EVENT STARTS ENDS AT START END TIME DURATION ARROW FROM TO
2220 %token <number> MAPPING NONE FRAME MOTION BEZIER_CUBIC LINEAR CATMULL_ROM
2221 %token <number> BSPLINE STATIC
2222 %token <number> SEMANTICS EXTERNAL INTERNAL ALIGNMENT RG BA FOR ALPHA
2223 %token <number> TIMEBASE MARKER POINTER
2224 %token <number> SIMPLE_TIMED_GLYPH_MARKER
2225 %token <number> SIMPLE_TIMED_GLYPH_STYLE_MORPH
2226 %token <number> GLYPH PAUSE IN MORPH SECONDARY
2227 %token <number> PATH SECTION PERIODIC
2228 %token <number> DIRECTIONALITY L2R_T2B R2L_T2B T2B_R2L T2B_L2R
2229 %token <number> BITMAP PALETTE COLORS
2230 %token <number> FONT RANGE FIRST LAST CODE POINT
2231 %token <number> USER SOURCE PNG DRAW VISIBLE
2232 %token <number> ID BOLD ITALICS UNDERLINE STRIKE JUSTIFY
2233 %token <number> BASE OFFSET GRANULE RATE SHIFT WIDTH HEIGHT CANVAS
2234 %token <number> LEFT TOP RIGHT BOTTOM MARGIN MARGINS
2235 %token <number> HORIZONTAL VERTICAL CLIP PRE MARKUP
2236 %token <number> LOCAL WRAP WORD META
2237 
2238 %token <number> NUMBER
2239 %token <unumber> UNUMBER
2240 %token <string> STRING
2241 %token <fp> FLOAT
2242 %token <color> COLORSPEC
2243 %token <string> IDENTIFIER MACRO_BODY
2244 
2245 %type <number> kd_kate kd_opt_defs kd_defs kd_def kd_events kd_event
2246 %type <number> kd_curve_points kd_palette_colors
2247 %type <number> kd_bitmap_pixels kd_png_bitmap_pixels
2248 %type <number> kd_style_defs kd_style_def
2249 %type <number> kd_region_defs kd_region_def
2250 %type <number> kd_curve_defs kd_curve_def
2251 %type <number> kd_palette_defs kd_palette_def
2252 %type <number> kd_bitmap_defs kd_bitmap_def
2253 %type <number> kd_font_range_defs kd_font_range_def
2254 %type <number> kd_font_mapping_defs kd_font_mapping_def
2255 %type <string> kd_opt_name
2256 %type <number> kd_style_name_or_index
2257 %type <number> kd_region_name_or_index
2258 %type <number> kd_curve_name_or_index kd_curve_def_name_or_index
2259 %type <number> kd_palette_name_or_index
2260 %type <number> kd_bitmap_name_or_index
2261 %type <number> kd_motion_name_or_index
2262 %type <number> kd_font_range_name_or_index
2263 %type <number> kd_font_mapping_name_or_index
2264 %type <fp> kd_optional_curve_duration
2265 %type <fp> float timespec
2266 %type <number> kd_event_defs kd_event_def
2267 %type <number> kd_motion_defs kd_motion_def
2268 %type <number> kd_motion_mapping kd_motion_semantics
2269 %type <number> kd_curvetype
2270 %type <color> kd_color
2271 %type <number> kd_simple_timed_glyph_marker_defs kd_simple_timed_glyph_marker_def
2272 %type <number> kd_simple_timed_glyph_style_morph_defs kd_simple_timed_glyph_style_morph_def
2273 %type <number> kd_opt_comma
2274 %type <number> bitmap_x_offset bitmap_y_offset
2275 %type <fp> float60
2276 %type <unumber> unumber60
2277 %type <dynstring> strings
2278 %type <number> kd_optional_secondary
2279 %type <number> directionality
2280 %type <number> kd_opt_space_metric
2281 %type <number> kd_wrap_mode
2282 %type <number> kd_meta_byte_stream_def kd_byte_stream
2283 
2284 %%
2285 
2286 kd_kate: {nlines=1;} KATE '{' kd_opt_defs { kd_write_headers(); } kd_events '}' { cleanup_memory(); }
2287        ;
2288 
2289 kd_opt_defs: DEFS '{' kd_defs '}'
2290            | {}
2291            ;
2292 
2293 kd_defs: kd_defs kd_def
2294        | {}
2295        ;
2296 
2297 kd_def: LANGUAGE STRING { CHECK_KATE_API_ERROR(kate_info_set_language(&ki,$2)); }
2298       | CATEGORY STRING { CHECK_KATE_API_ERROR(kate_info_set_category(&ki,$2)); }
2299       | DIRECTIONALITY directionality { CHECK_KATE_API_ERROR(kate_info_set_text_directionality(&ki,$2)); }
2300       | COMMENT STRING { add_comment(&kc,$2); }
2301       | DEFINE MACRO {set_macro_mode();} IDENTIFIER {record_macro_name($4);} MACRO_BODY
2302                      { add_temp_macro($6); unset_macro_mode(); }
2303       | DEFINE STYLE kd_opt_name {init_style(&kstyle);} '{' kd_style_defs '}' { add_style(&ki,$3,&kstyle); }
2304       | DEFINE REGION kd_opt_name {init_region(&kregion);} '{' kd_region_defs '}' { add_region(&ki,$3,&kregion); }
2305       | DEFINE CURVE kd_opt_name {init_curve();} '{' kd_curve_defs '}' { add_curve(&ki,$3,kcurve.curve); }
2306       | DEFINE MOTION kd_opt_name {init_motion();} '{' kd_motion_defs '}' { add_motion(&ki,$3,kmotion); }
2307       | DEFINE PALETTE kd_opt_name {init_palette();} '{' kd_palette_defs '}' { add_palette(&ki,$3,kpalette.palette); }
2308       | DEFINE BITMAP kd_opt_name {init_bitmap();} '{' kd_bitmap_defs '}' { add_bitmap(&ki,$3,kbitmap.bitmap); }
2309       | DEFINE FONT RANGE kd_opt_name {init_font_range();} '{' kd_font_range_defs '}' { add_font_range(&ki,$4,krange); }
2310       | DEFINE FONT MAPPING kd_opt_name {init_font_mapping();} '{' kd_font_mapping_defs '}' { add_font_mapping(&ki,$4,kmapping); }
2311       | TIMEBASE timespec { timebase=$2; }
2312       | GRANULE RATE UNUMBER '/' UNUMBER {set_granule_rate($3,$5);}
2313       | GRANULE SHIFT UNUMBER {set_granule_shift($3);}
2314       | CANVAS SIZE UNUMBER UNUMBER {set_canvas_size($3,$4);}
2315       ;
2316 
2317 kd_style_defs: kd_style_defs kd_style_def
2318              | {}
2319              ;
2320 
2321 kd_style_def: HALIGN float { kstyle.halign=$2; }
2322             | VALIGN float { kstyle.valign=$2; }
2323             | HLEFT { kstyle.halign=(kate_float)-1.0; }
2324             | HCENTER { kstyle.halign=(kate_float)0.0; }
2325             | HRIGHT { kstyle.halign=(kate_float)1.0; }
2326             | VTOP { kstyle.valign=(kate_float)-1.0; }
2327             | VCENTER { kstyle.valign=(kate_float)0.0; }
2328             | VBOTTOM { kstyle.valign=(kate_float)1.0; }
2329             | TEXT COLOR kd_color { set_color(&kstyle.text_color,$3); }
2330             | BACKGROUND COLOR kd_color { set_color(&kstyle.background_color,$3); }
2331             | DRAW COLOR kd_color { set_color(&kstyle.draw_color,$3); }
2332             | BOLD { kstyle.bold=1; }
2333             | ITALICS { kstyle.italics=1; }
2334             | UNDERLINE { kstyle.underline=1; }
2335             | STRIKE { kstyle.strike=1; }
2336             | JUSTIFY { kstyle.justify=1; }
2337             | WRAP kd_wrap_mode { kstyle.wrap_mode=$2; }
2338             | FONT STRING { set_font(&kstyle,$2); }
2339             | FONT SIZE float kd_opt_space_metric { set_font_size(&kstyle,$3,$4); }
2340             | FONT WIDTH float kd_opt_space_metric { set_font_width(&kstyle,$3,$4); }
2341             | FONT HEIGHT float kd_opt_space_metric { set_font_height(&kstyle,$3,$4); }
2342             | LEFT MARGIN float kd_opt_space_metric { set_margin(&kstyle,&kstyle.left_margin,$3,$4); }
2343             | TOP MARGIN float kd_opt_space_metric { set_margin(&kstyle,&kstyle.top_margin,$3,$4); }
2344             | RIGHT MARGIN float kd_opt_space_metric { set_margin(&kstyle,&kstyle.right_margin,$3,$4); }
2345             | BOTTOM MARGIN float kd_opt_space_metric { set_margin(&kstyle,&kstyle.bottom_margin,$3,$4); }
2346             | MARGINS float kd_opt_space_metric float kd_opt_space_metric float kd_opt_space_metric float kd_opt_space_metric
2347                   { set_margins(&kstyle,$2,$3,$4,$5,$6,$7,$8,$9); }
2348             | META STRING '=' STRING { add_meta(&kstyle.meta,$2,$4); }
2349             | META STRING '=' UNUMBER {init_byte_stream($4);} '{' kd_byte_stream '}' { add_meta_byte_stream(&kstyle.meta,$2); }
2350             ;
2351 
2352 kd_opt_space_metric: '%' { $$=kate_percentage; }
2353                    | 'm' { $$=kate_millionths; }
2354                    | { $$=kate_pixel; }
2355                    ;
2356 
2357 kd_region_defs: kd_region_defs kd_region_def
2358               | {}
2359               ;
2360 
2361 kd_region_def: METRIC {kregion.metric=$1; }
2362              | POSITION float float { kregion.x=$2;kregion.y=$3; }
2363              | SIZE float float { kregion.w=$2;kregion.h=$3; }
2364              | CLIP { kregion.clip=1; }
2365              | DEFAULT STYLE kd_style_name_or_index { kregion.style=$3; }
2366              | META STRING '=' STRING { add_meta(&kregion.meta,$2,$4); }
2367              | META STRING '=' UNUMBER {init_byte_stream($4);} '{' kd_byte_stream '}' { add_meta_byte_stream(&kregion.meta,$2); }
2368              ;
2369 
2370 kd_curve_defs: kd_curve_defs kd_curve_def
2371               | {}
2372               ;
2373 
2374 kd_curve_def: kd_curvetype { kcurve.curve->type=$1; n_curve_pts=0; }
2375             | UNUMBER POINTS { init_curve_points($1); } '{' kd_curve_points '}' {
2376                 if ((size_t)n_curve_pts!=kcurve.curve->npts*2) katedesc_error("Wrong number of points in the curve");
2377               }
2378             | POINTS { init_open_ended_curve_points(); } '{' kd_curve_points '}'
2379             ;
2380 
2381 kd_palette_defs: kd_palette_defs kd_palette_def
2382                | {}
2383                ;
2384 
2385 kd_palette_def: UNUMBER COLORS { init_palette_colors($1); } '{' kd_palette_colors '}' {
2386                   if ((size_t)n_palette_colors!=kpalette.palette->ncolors) {
2387                     katedesc_error("Wrong number of colors in the palette");
2388                   }
2389                 }
2390               | SOURCE STRING { load_palette($2); }
2391               ;
2392 
2393 kd_bitmap_defs: kd_bitmap_defs kd_bitmap_def
2394               | {}
2395               ;
2396 
2397 kd_bitmap_def: UNUMBER 'x' UNUMBER 'x' UNUMBER { init_bitmap_pixels($1,$3,$5); } '{' kd_bitmap_pixels '}' {
2398                  if ((size_t)n_bitmap_pixels!=kbitmap.bitmap->width*kbitmap.bitmap->height) {
2399                    katedesc_error("Wrong number of pixels in the bitmap");
2400                  }
2401                }
2402              | UNUMBER 'x' UNUMBER PNG UNUMBER { init_png_bitmap_pixels($1,$3,$5); } '{' kd_png_bitmap_pixels '}' {
2403                  if ((size_t)n_bitmap_pixels!=kbitmap.bitmap->size) {
2404                    katedesc_error("Wrong number of bytes in the PNG bitmap");
2405                  }
2406                }
2407              | SOURCE STRING { load_bitmap($2,0); }
2408              | DEFAULT PALETTE kd_palette_name_or_index { kbitmap.bitmap->palette=$3; }
2409              | OFFSET bitmap_x_offset bitmap_y_offset { kbitmap.bitmap->x_offset=$2; kbitmap.bitmap->y_offset=$3; }
2410              | META STRING '=' STRING { add_meta(&kbitmap.bitmap->meta,$2,$4); }
2411              | META STRING '=' UNUMBER {init_byte_stream($4);} '{' kd_byte_stream '}' { add_meta_byte_stream(&kbitmap.bitmap->meta,$2); }
2412              ;
2413 
2414 kd_color: UNUMBER UNUMBER UNUMBER { $$=make_color($1,$2,$3,255); }
2415         | UNUMBER UNUMBER UNUMBER UNUMBER { $$=make_color($1,$2,$3,$4); }
2416         | COLORSPEC { $$=make_color_alpha($1,255); }
2417         | COLORSPEC ALPHA UNUMBER { $$=make_color_alpha($1,$3); }
2418         ;
2419 
2420 kd_wrap_mode: NONE { $$=kate_wrap_none; }
2421             | WORD { $$=kate_wrap_word; }
2422             ;
2423 
2424 kd_curvetype: NONE { $$=kate_curve_none; }
2425             | STATIC { $$=kate_curve_static; }
2426             | LINEAR { $$=kate_curve_linear; }
2427             | CATMULL_ROM { $$=kate_curve_catmull_rom_spline; }
2428             | BEZIER_CUBIC { $$=kate_curve_bezier_cubic_spline; }
2429             | BSPLINE { $$=kate_curve_bspline; }
2430             ;
2431 
2432 kd_curve_points: kd_curve_points float {
2433                    if (open_ended_curve) {
2434                      add_open_ended_curve_point($2);
2435                    }
2436                    else {
2437                      if ((size_t)n_curve_pts>=kcurve.curve->npts*2) katedesc_error("Too many points in curve");
2438                      else { kcurve.curve->pts[n_curve_pts++]=$2; }
2439                    }
2440                  }
2441                | {}
2442                ;
2443 
2444 kd_palette_colors: kd_palette_colors '{' kd_color '}' kd_opt_comma {
2445                      if ((size_t)n_palette_colors>=kpalette.palette->ncolors) katedesc_error("Too many colors in palette");
2446                      else { set_color(&kpalette.palette->colors[n_palette_colors++],$3); }
2447                    }
2448                  | {}
2449                  ;
2450 
2451 kd_bitmap_pixels: kd_bitmap_pixels UNUMBER kd_opt_comma {
2452                     if ((size_t)n_bitmap_pixels>=kbitmap.bitmap->width*kbitmap.bitmap->height) {
2453                       katedesc_error("Too many pixels in bitmap");
2454                     }
2455                     else {
2456                       if ($2>(unsigned int)(1<<kbitmap.bitmap->bpp)-1) {
2457                         katedesc_error("pixels out of range for given bpp");
2458                       }
2459                       else {
2460                         kbitmap.bitmap->pixels[n_bitmap_pixels++]=$2;
2461                       }
2462                     }
2463                   }
2464                 | {}
2465                 ;
2466 
2467 kd_png_bitmap_pixels: kd_png_bitmap_pixels UNUMBER kd_opt_comma {
2468                         if ((size_t)n_bitmap_pixels>=kbitmap.bitmap->size) {
2469                           katedesc_error("Too many pixels in bitmap");
2470                         }
2471                         else {
2472                           kbitmap.bitmap->pixels[n_bitmap_pixels++]=$2;
2473                         }
2474                       }
2475                     | {}
2476                     ;
2477 
2478 kd_byte_stream: kd_byte_stream UNUMBER kd_opt_comma {
2479                         if (n_bytes_in_stream>=byte_stream_size) {
2480                           katedesc_error("Too many bytes in byte stream");
2481                         }
2482                         else {
2483                           byte_stream[n_bytes_in_stream++]=$2;
2484                         }
2485                       }
2486               | {}
2487               ;
2488 
2489 kd_opt_name: STRING { $$=$1; }
2490            | { $$=NULL; }
2491            ;
2492 
2493 kd_style_name_or_index: STRING { $$=find_style(&ki,$1); }
2494                       | UNUMBER { if ($1>=ki.nstyles) yyerrorf("Invalid style index (%u/%d)",$1,ki.nstyles); $$=$1; }
2495                       ;
2496 
2497 kd_region_name_or_index: STRING { $$=find_region(&ki,$1); }
2498                       | UNUMBER { if ($1>=ki.nregions) yyerrorf("Invalid region index (%u/%u)",$1,ki.nregions); $$=$1; }
2499                       ;
2500 
2501 kd_curve_name_or_index: STRING { $$=find_curve(&ki,$1); }
2502                       | UNUMBER { if ($1>=ki.ncurves) yyerrorf("Invalid curve index (%u/%u)",$1,ki.ncurves); $$=$1; }
2503                       ;
2504 
2505 kd_motion_name_or_index: STRING { $$=find_motion(&ki,$1); }
2506                        | UNUMBER { if ($1>=ki.nmotions) yyerrorf("Invalid motion index (%u/%u)",$1,ki.nmotions); $$=$1; }
2507                        ;
2508 
2509 kd_palette_name_or_index: STRING { $$=find_palette(&ki,$1); }
2510                         | UNUMBER { if ($1>=ki.npalettes) yyerrorf("Invalid palette index (%u/%u)",$1,ki.npalettes); $$=$1; }
2511                         ;
2512 
2513 kd_bitmap_name_or_index: STRING { $$=find_bitmap(&ki,$1); }
2514                        | UNUMBER { if ($1>=ki.nbitmaps) yyerrorf("Invalid bitmap index (%u/%u)",$1,ki.nbitmaps); $$=$1; }
2515                        ;
2516 
2517 kd_font_range_name_or_index: STRING { $$=find_font_range(&ki,$1); }
2518                            | UNUMBER { if ($1>=ki.nfont_ranges) yyerrorf("Invalid font range index (%u/%u)",$1,ki.nfont_ranges); $$=$1; }
2519                            ;
2520 
2521 kd_font_mapping_name_or_index: STRING { $$=find_font_mapping(&ki,$1); }
2522                              | UNUMBER { if ($1>=ki.nfont_mappings) yyerrorf("Invalid font mapping index (%u/%u)",$1,ki.nfont_mappings); $$=$1; }
2523                              ;
2524 
2525 kd_curve_def_name_or_index: kd_curve_name_or_index { reference_curve_from($1); }
2526                           | { init_curve(); } '{' kd_curve_defs '}' {}
2527                           | kd_curve_name_or_index { init_curve_from($1); } '{' kd_curve_defs '}' {}
2528                           ;
2529 
2530 
2531 float: FLOAT { $$=$1; }
2532      | UNUMBER { $$=(kate_float)$1; }
2533      | NUMBER { $$=(kate_float)$1; }
2534      ;
2535 
2536 bitmap_x_offset: UNUMBER { $$=$1; }
2537                | NUMBER { $$=$1; }
2538                | float '%' { $$=compute_bitmap_x_offset($1); }
2539                ;
2540 
2541 bitmap_y_offset: UNUMBER { $$=$1; }
2542                | NUMBER { $$=$1; }
2543                | float '%' { $$=compute_bitmap_y_offset($1); }
2544                ;
2545 
2546 timespec: UNUMBER ':' unumber60 ':' float60 { $$=$1*3600+$3*60+$5; }
2547         | UNUMBER ':' float60 { $$=$1*60+$3; }
2548         | float60 { $$=$1; }
2549         ;
2550 
2551 kd_events: kd_events kd_event
2552          | {}
2553          ;
2554 
2555 kd_event: EVENT { init_event(&kevent); } '{' kd_event_defs '}' {
2556             check_event(&kevent); kd_encode_text(&k,&kevent); clear_event(&kevent);
2557           }
2558         | EVENT { init_event(&kevent); } kd_event_defs {
2559             check_event(&kevent); kd_encode_text(&k,&kevent); clear_event(&kevent);
2560           }
2561         ;
2562 
2563 kd_event_defs: kd_event_defs kd_event_def
2564              | {}
2565              ;
2566 
2567 kd_event_def: ID UNUMBER { kd_encode_set_id(&k,$2); }
2568             | LANGUAGE STRING { kd_encode_set_language(&k,$2); }
2569             | DIRECTIONALITY directionality { CHECK_KATE_API_ERROR(kate_encode_set_text_directionality(&k,$2)); }
2570             | STARTS AT timespec { set_event_t0(&kevent,$3); }
2571             | ENDS AT timespec { set_event_t1(&kevent,$3); }
2572             | START TIME timespec { set_event_t0(&kevent,$3); }
2573             | END TIME timespec { set_event_t1(&kevent,$3); }
2574             | FROM timespec TO timespec { set_event_t0_t1(&kevent,$2,$4); }
2575             | DURATION timespec { set_event_duration(&kevent,$2); }
2576             | FROM timespec FOR timespec { set_event_t0(&kevent,$2); set_event_duration(&kevent,$4); }
2577             | timespec ARROW timespec { set_event_t0_t1(&kevent,$1,$3); }
2578             | REGION kd_region_name_or_index { set_event_region_index(&kevent,$2); }
2579             | REGION kd_region_name_or_index { init_region_from($2); } '{' kd_region_defs '}'
2580                      { set_event_region(&kevent,&kregion); }
2581             | REGION { init_region(&kregion); } '{' kd_region_defs '}' { set_event_region(&kevent,&kregion); }
2582             | kd_optional_secondary STYLE kd_style_name_or_index
2583                     { if ($1) set_event_secondary_style_index(&kevent,$3); else set_event_style_index(&kevent,$3); }
2584             | kd_optional_secondary STYLE kd_style_name_or_index {init_style_from($3); } '{' kd_style_defs '}'
2585                     { if ($1) set_event_secondary_style(&kevent,&kstyle); else set_event_style(&kevent,&kstyle); }
2586             | kd_optional_secondary STYLE { init_style(&kstyle); } '{' kd_style_defs '}'
2587                     { if ($1) set_event_secondary_style(&kevent,&kstyle); else set_event_style(&kevent,&kstyle); }
2588             | TEXT strings { set_event_text(&kevent,$2,0,0); kate_free($2); }
2589             | PRE TEXT strings { set_event_text(&kevent,$3,1,0); kate_free($3); }
2590             | MARKUP strings { set_event_text(&kevent,$2,0,1); kate_free($2); }
2591             | PRE MARKUP strings { set_event_text(&kevent,$3,1,1); kate_free($3); }
2592             | TEXT SOURCE STRING { set_event_text_from(&kevent,$3,0,0); }
2593             | PRE TEXT SOURCE STRING { set_event_text_from(&kevent,$4,1,0); }
2594             | MARKUP SOURCE STRING { set_event_text_from(&kevent,$3,0,1); }
2595             | PRE MARKUP SOURCE STRING { set_event_text_from(&kevent,$4,1,1); }
2596             | strings { set_event_text(&kevent,$1,0,0); kate_free($1); }
2597             | MOTION { init_motion(); } '{' kd_motion_defs '}' { kd_add_event_motion(kmotion); }
2598             | MOTION kd_motion_name_or_index { kd_add_event_motion_index($2); }
2599             | SIMPLE_TIMED_GLYPH_MARKER {init_simple_glyph_pointer_motion(); } '{' kd_simple_timed_glyph_marker_defs '}'
2600                     { kd_finalize_simple_timed_glyph_motion(kmotion); kd_add_event_motion(kmotion); }
2601             | SIMPLE_TIMED_GLYPH_STYLE_MORPH {init_simple_glyph_pointer_motion(); } '{' kd_simple_timed_glyph_style_morph_defs '}'
2602                     { kd_finalize_simple_timed_glyph_motion(kmotion); kd_add_event_motion(kmotion); }
2603             | FONT MAPPING kd_font_mapping_name_or_index { CHECK_KATE_API_ERROR(kate_encode_set_font_mapping_index(&k,$3)); }
2604             | PALETTE kd_palette_name_or_index { set_event_palette_index(&kevent,$2); }
2605             | PALETTE { init_palette(); } '{' kd_palette_defs '}' { set_event_palette(&kevent,kpalette.palette); }
2606             | BITMAP kd_bitmap_name_or_index { set_event_bitmap_index(&kevent,$2); }
2607             | BITMAP { init_bitmap(); } '{' kd_bitmap_defs '}' { set_event_bitmap(&kevent,kbitmap.bitmap); }
2608             | DEFINE LOCAL BITMAP kd_opt_name {init_bitmap();} '{' kd_bitmap_defs '}' { add_local_bitmap(&k,$4,kbitmap.bitmap); }
2609             | DEFINE LOCAL BITMAP kd_opt_name '=' kd_bitmap_name_or_index { add_local_bitmap_index(&k,$4,$6); }
2610             | META STRING '=' STRING { kd_add_event_meta($2,$4); }
2611             | META STRING '=' kd_meta_byte_stream_def { kd_add_event_meta_byte_stream($2); }
2612             ;
2613 
2614 kd_meta_byte_stream_def: UNUMBER {init_byte_stream($1);} '{' kd_byte_stream '}' { $$=0; }
2615                        ;
2616 
2617 kd_optional_secondary: SECONDARY { $$=1; }
2618                      | { $$=0; }
2619                      ;
2620 
2621 strings: strings '+' STRING { $$=catstrings($1,$3); }
2622        | STRING { $$=catstrings(NULL,$1); }
2623        ;
2624 
2625 kd_motion_defs: kd_motion_defs kd_motion_def
2626               | {}
2627               ;
2628 
2629 kd_motion_def: MAPPING kd_motion_mapping { set_motion_mapping(kmotion,$2,$2); }
2630              | MAPPING kd_motion_mapping kd_motion_mapping { set_motion_mapping(kmotion,$2,$3); }
2631              | SEMANTICS kd_motion_semantics { set_motion_semantics(kmotion,$2); }
2632              | CURVE kd_curve_def_name_or_index kd_optional_curve_duration { add_curve_to_motion(kmotion,$3); }
2633              | PERIODIC { kmotion->periodic=1; }
2634              ;
2635 
2636 kd_optional_curve_duration: FOR float { $$=$2; }
2637                           | FOR float '%' { $$=-$2/(kate_float)100.0; }
2638                           | FOR float 'm' { $$=-$2/(kate_float)1000000.0; }
2639                           | { $$=(kate_float)-1.0; }
2640                           ;
2641 
2642 kd_motion_mapping: NONE { $$=kate_motion_mapping_none; }
2643                  | FRAME { $$=kate_motion_mapping_frame; }
2644                  | REGION { $$=kate_motion_mapping_region; }
2645                  | EVENT DURATION { $$=kate_motion_mapping_event_duration; }
2646                  | BITMAP SIZE { $$=kate_motion_mapping_bitmap_size; }
2647                  | USER UNUMBER {
2648                      if ($2<kate_motion_mapping_user) yyerrorf("invalid value for user motion mapping (%u), should be 128 or more",$2);
2649                      $$=(kate_motion_mapping)$2;
2650                    }
2651                  ;
2652 
2653 kd_motion_semantics: TIME { $$=kate_motion_semantics_time; }
2654                    | REGION POSITION { $$=kate_motion_semantics_region_position; }
2655                    | REGION SIZE { $$=kate_motion_semantics_region_size; }
2656                    | TEXT ALIGNMENT { $$=kate_motion_semantics_text_alignment_int; }
2657                    | INTERNAL TEXT ALIGNMENT { $$=kate_motion_semantics_text_alignment_int; }
2658                    | EXTERNAL TEXT ALIGNMENT { $$=kate_motion_semantics_text_alignment_ext; }
2659                    | TEXT POSITION { $$=kate_motion_semantics_text_position; }
2660                    | TEXT SIZE { $$=kate_motion_semantics_text_size; }
2661                    | MARKER UNUMBER POSITION { $$=kd_get_marker_position_semantics($2); }
2662                    | GLYPH POINTER UNUMBER { $$=kd_get_glyph_pointer_semantics($3); }
2663                    | TEXT COLOR RG { $$=kate_motion_semantics_text_color_rg; }
2664                    | TEXT COLOR BA { $$=kate_motion_semantics_text_color_ba; }
2665                    | BACKGROUND COLOR RG { $$=kate_motion_semantics_background_color_rg; }
2666                    | BACKGROUND COLOR BA { $$=kate_motion_semantics_background_color_ba; }
2667                    | DRAW COLOR RG { $$=kate_motion_semantics_draw_color_rg; }
2668                    | DRAW COLOR BA { $$=kate_motion_semantics_draw_color_ba; }
2669                    | STYLE MORPH { $$=kate_motion_semantics_style_morph; }
2670                    | TEXT PATH { $$=kate_motion_semantics_text_path; }
2671                    | TEXT PATH SECTION { $$=kate_motion_semantics_text_path_section; }
2672                    | DRAW { $$=kate_motion_semantics_draw; }
2673                    | VISIBLE SECTION { $$=kate_motion_semantics_text_visible_section; }
2674                    | 'z' { $$=kate_motion_semantics_z; }
2675                    | HORIZONTAL MARGINS { $$=kate_motion_semantics_horizontal_margins; }
2676                    | VERTICAL MARGINS { $$=kate_motion_semantics_vertical_margins; }
2677                    | BITMAP POSITION { $$=kate_motion_semantics_bitmap_position; }
2678                    | BITMAP SIZE { $$=kate_motion_semantics_bitmap_size; }
2679                    | MARKER UNUMBER BITMAP { $$=kd_get_marker_bitmap_semantics($2); }
2680                    | GLYPH POINTER UNUMBER BITMAP { $$=kd_get_glyph_pointer_bitmap_semantics($3); }
2681                    | DRAW WIDTH { $$=kate_motion_semantics_draw_width; }
2682                    | USER UNUMBER {
2683                        if ($2<kate_motion_semantics_user) yyerrorf("invalid value for user motion semantics (%u), should be 128 or more",$2);
2684                        $$=(kate_motion_semantics)$2;
2685                      }
2686                    ;
2687 
2688 kd_simple_timed_glyph_marker_defs: kd_simple_timed_glyph_marker_defs kd_simple_timed_glyph_marker_def
2689                                  | {}
2690                                  ;
2691 
2692 kd_simple_timed_glyph_marker_def: GLYPH POINTER UNUMBER { kmotion->semantics=get_glyph_pointer_offset($3); }
2693                                 | 'Y' MAPPING kd_motion_mapping { kmotion->y_mapping=$3; }
2694                                 | HEIGHT FROM float TO float { karaoke_base_height=$3; karaoke_top_height=$5; }
2695                                 | PAUSE FOR timespec { add_glyph_pause($3,(kate_float)0.0); }
2696                                 | GLYPH UNUMBER IN timespec { add_glyph_transition($2,$4,(kate_float)0.0,(kate_float)1.0,0,(kate_float)0.0); }
2697                                 | GLYPH UNUMBER AT timespec { add_glyph_transition($2,$4,(kate_float)0.0,(kate_float)1.0,1,(kate_float)0.0); }
2698                                 ;
2699 
2700 kd_simple_timed_glyph_style_morph_defs: kd_simple_timed_glyph_style_morph_defs kd_simple_timed_glyph_style_morph_def
2701                                       | {}
2702                                       ;
2703 
2704 kd_simple_timed_glyph_style_morph_def: GLYPH POINTER UNUMBER { kmotion->semantics=get_glyph_pointer_offset($3); }
2705                                      | FROM STYLE kd_style_name_or_index TO STYLE kd_style_name_or_index
2706                                               { set_style_morph(&kevent,$3,$6); }
2707                                      | PAUSE FOR timespec { add_glyph_pause($3,(kate_float)0.0); }
2708                                      | GLYPH UNUMBER IN timespec { add_glyph_transition($2,$4,(kate_float)0.0,(kate_float)0.0,0,(kate_float)1.0); }
2709                                      | GLYPH UNUMBER AT timespec { add_glyph_transition($2,$4,(kate_float)0.0,(kate_float)0.0,1,(kate_float)1.0); }
2710                                      | STRING IN timespec { add_glyph_transition_to_text($1,$3,(kate_float)0.0,(kate_float)0.0,0,(kate_float)1.0); }
2711                                      | STRING AT timespec { add_glyph_transition_to_text($1,$3,(kate_float)0.0,(kate_float)0.0,1,(kate_float)1.0); }
2712                                      ;
2713 
2714 unumber60: UNUMBER { if ($1>59) yyerrorf("Value must be between 0 and 59, but is %u",$1); } { $$=$1; }
2715          ;
2716 
2717 float60: float { if ($1<(kate_float)0.0 || $1>=(kate_float)60.0) yyerrorf("Value must be between 0 (inclusive) and 60 (exclusive), but is %f",$1); } { $$=$1; }
2718        ;
2719 
2720 kd_opt_comma: ',' {}
2721             | {}
2722             ;
2723 
2724 directionality: L2R_T2B { $$=kate_l2r_t2b; }
2725               | R2L_T2B { $$=kate_r2l_t2b; }
2726               | T2B_R2L { $$=kate_t2b_r2l; }
2727               | T2B_L2R { $$=kate_t2b_l2r; }
2728               ;
2729 
2730 kd_font_range_defs: kd_font_range_defs kd_font_range_def
2731                   | {}
2732                   ;
2733 
2734 kd_font_range_def: FIRST CODE POINT STRING { set_font_range_first_code_point_string($4); }
2735                  | FIRST CODE POINT UNUMBER { set_font_range_first_code_point($4); }
2736                  | LAST CODE POINT STRING { set_font_range_last_code_point_string($4); }
2737                  | LAST CODE POINT UNUMBER { set_font_range_last_code_point($4); }
2738                  | FIRST BITMAP kd_bitmap_name_or_index { set_font_range_first_bitmap($3); }
2739                  ;
2740 
2741 kd_font_mapping_defs: kd_font_mapping_defs kd_font_mapping_def
2742                     | {}
2743                     ;
2744 
2745 kd_font_mapping_def: RANGE {init_font_range();} '{' kd_font_range_defs '}' { add_font_range_to_mapping(); }
2746                    | RANGE kd_font_range_name_or_index { krange=ki.font_ranges[$2]; add_font_range_to_mapping(); }
2747                    ;
2748 
2749 %%
2750 
2751