1 /* Copyright (C) 2008, 2009 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 #define KATE_INTERNAL
11 #include "kate_internal.h"
12
13 #ifdef HAVE_STDLIB_H
14 #include <stdlib.h>
15 #endif
16 #ifdef HAVE_STRING_H
17 #include <string.h>
18 #endif
19 #include "kate/kate.h"
20
21 /**
22 \ingroup info
23 Initializes a kate_info structure.
24 When done, it should be clear using kate_info_clear.
25 \param ki the kate_info structure to initialize
26 \returns 0 success
27 \returns KATE_E_* error
28 */
kate_info_init(kate_info * ki)29 int kate_info_init(kate_info *ki)
30 {
31 if (!ki) return KATE_E_INVALID_PARAMETER;
32
33 ki->bitstream_version_major=KATE_BITSTREAM_VERSION_MAJOR;
34 ki->bitstream_version_minor=KATE_BITSTREAM_VERSION_MINOR;
35
36 ki->num_headers=0;
37
38 /* default to a sensible granule encoding */
39 ki->granule_shift=32;
40 ki->gps_numerator=1000;
41 ki->gps_denominator=1;
42
43 ki->text_encoding=kate_utf8;
44 ki->text_directionality=kate_l2r_t2b;
45 ki->text_markup_type=kate_markup_none;
46
47 ki->language=NULL;
48 ki->category=NULL;
49
50 ki->nregions=0;
51 ki->regions=NULL;
52 ki->nstyles=0;
53 ki->styles=NULL;
54 ki->ncurves=0;
55 ki->curves=NULL;
56 ki->nmotions=0;
57 ki->motions=NULL;
58 ki->npalettes=0;
59 ki->palettes=NULL;
60 ki->nbitmaps=0;
61 ki->bitmaps=NULL;
62 ki->nfont_ranges=0;
63 ki->font_ranges=NULL;
64 ki->nfont_mappings=0;
65 ki->font_mappings=NULL;
66
67 ki->original_canvas_width=0;
68 ki->original_canvas_height=0;
69
70 ki->remove_markup=0;
71 ki->no_limits=0;
72 ki->probe=0;
73
74 return 0;
75 }
76
kate_make_fraction(kate_float resolution,kate_uint32_t * numerator,kate_uint32_t * denominator)77 static void kate_make_fraction(kate_float resolution,kate_uint32_t *numerator,kate_uint32_t *denominator)
78 {
79 if (resolution<1) {
80 *numerator=(kate_uint32_t)(1000/resolution+(kate_float)0.5);
81 *denominator=1000;
82 }
83 else {
84 *numerator=1000;
85 *denominator=(kate_uint32_t)(resolution*1000+(kate_float)0.5);
86 }
87 }
88
89 /**
90 \ingroup info
91 Sets up the granule encoding parameters so that events may be timestamped with the given
92 resolution, and may not last longer than the given lifetime.
93 \param ki the kate_info structure to set the granule encoding parameters in.
94 \param resolution the timestamping resolution, in seconds (eg, 0.001 means millisecond resolution)
95 \param max_length the maximum time we need to represent, in seconds
96 \param max_event_lifetime the maximum time an event may last, in seconds
97 \returns 0 success
98 \returns KATE_E_* error
99 */
kate_info_set_granule_encoding(kate_info * ki,kate_float resolution,kate_float max_length,kate_float max_event_lifetime)100 int kate_info_set_granule_encoding(kate_info *ki,kate_float resolution,kate_float max_length,kate_float max_event_lifetime)
101 {
102 kate_float offset_granules;
103 unsigned char offset_bits,bits;
104 kate_float base_min_resolution;
105
106 if (!ki || resolution<=0 || max_event_lifetime<0) return KATE_E_INVALID_PARAMETER;
107
108 offset_granules=max_event_lifetime/resolution;
109 offset_bits=0;
110 while (offset_granules>=1) {
111 ++offset_bits;
112 if (offset_bits>=64) return KATE_E_BAD_GRANULE;
113 offset_granules/=2;
114 }
115
116 base_min_resolution=max_length;
117 bits=offset_bits;
118 while (bits<62) {
119 ++bits;
120 base_min_resolution/=2;
121 }
122
123 ki->granule_shift=offset_bits;
124 kate_make_fraction(resolution,&ki->gps_numerator,&ki->gps_denominator);
125
126 if (base_min_resolution<=resolution) {
127 /* we can represent the required encoding */
128 return 0;
129 }
130 else {
131 /* we cannot represent the required encoding */
132 return KATE_E_BAD_GRANULE;
133 }
134 }
135
kate_replace_string(char ** sptr,const char * s,size_t len)136 static int kate_replace_string(char **sptr,const char *s,size_t len)
137 {
138 char *l=NULL;
139 int ret;
140
141 if (!sptr) return KATE_E_INVALID_PARAMETER;
142
143 ret=kate_check_add_overflow(len,1,NULL);
144 if (ret<0) return ret;
145
146 if (s) {
147 l=(char*)kate_malloc(len+1);
148 if (!l) return KATE_E_OUT_OF_MEMORY;
149 memcpy(l,s,len);
150 l[len]=0;
151 }
152
153 if (*sptr) kate_free(*sptr);
154 *sptr=l;
155
156 return 0;
157 }
158
159 /**
160 \ingroup info
161 Sets the default language for this bitstream.
162 The language should be a RFC 3066 language tag (most of the time, a ISO 639-1
163 code, optionally followed by a country secondary tag).
164 This function does some basic validation, and will truncate the tag according
165 to RFC 4646 rules. However, it may still accept some invalid tags.
166 The maximum length of a language tag is 15 characters. If RFC 4646 truncation
167 is possible, the tag will be truncated. If not, it will be rejected.
168 In case of truncation, the tag that was actually set may be read back from
169 the language field of the kate_info structure.
170 \param ki the kate_info structure for the stream
171 \param language the default language to set for this stream
172 \returns 0 success
173 \returns 1 success, but the tag was truncated (the resulting tag may be read back from ki->language)
174 \returns KATE_E_* error
175 */
kate_info_set_language(kate_info * ki,const char * language)176 int kate_info_set_language(kate_info *ki,const char *language)
177 {
178 int ret;
179 size_t len;
180 size_t new_len;
181 const char *sep;
182 int truncated;
183
184 if (!ki) return KATE_E_INVALID_PARAMETER;
185 if (!language) return KATE_E_INVALID_PARAMETER;
186
187 /* special case for empty string */
188 if (!*language) {
189 return kate_replace_string(&ki->language,language,0);
190 }
191
192 /* basic validation of allowed characters - won't catch all */
193 for (sep=language;*sep;++sep) {
194 int c=*sep;
195 if (c>='A' && c<='Z') continue;
196 if (c>='a' && c<='z') continue;
197 if (c>='0' && c<='9') continue;
198 if (c=='-' || c=='_') continue;
199 return KATE_E_INVALID_PARAMETER;
200 }
201
202 /* simple validity - the first tag must be 2 characters */
203 sep=strpbrk(language,"-_");
204 if (!sep) sep=language+strlen(language);
205 if (sep-language==0 || sep-language>3) return KATE_E_INVALID_PARAMETER;
206
207 /* if the tag is too long, it has to be truncated; while we still have space,
208 find the next - or _ following a tag of more than one character, and see
209 if we can fit it */
210 len=0;
211 new_len=0;
212 truncated=1;
213 while (truncated) {
214 size_t prev_new_len=new_len;
215 sep=strpbrk(language+new_len,"-_");
216 if (sep) {
217 new_len=sep-language;
218 }
219 else {
220 /* not found, gobble the remainder of the string */
221 new_len=strlen(language);
222 truncated=0;
223 }
224 /* maximum length of a subtag is 8 characters */
225 if (new_len-prev_new_len>8) {
226 return KATE_E_INVALID_PARAMETER;
227 }
228 if (new_len>15) {
229 /* we can't fit this new tag */
230 truncated=1;
231 break;
232 }
233 /* one or less character tags aren't allowed as the last tag */
234 if (new_len-prev_new_len>=2) {
235 /* so more than this is OK to keep */
236 len=new_len;
237 }
238 else {
239 /* but less we ignore if we have more to go, but complain if we're at the end */
240 if (!truncated) return KATE_E_INVALID_PARAMETER;
241 }
242 /* if we need another go, skip the separator */
243 ++new_len;
244 }
245
246 if (len<=1) {
247 /* we can't fit any subtag, or the first tag is less than 2 characters long */
248 return KATE_E_INVALID_PARAMETER;
249 }
250
251 ret=kate_replace_string(&ki->language,language,len);
252 if (ret<0) return ret;
253
254 return truncated?1:0;
255 }
256
257 /**
258 \ingroup info
259 Sets the default text directionality for this bitstream
260 \param ki the kate_info structure for the stream
261 \param text_directionality the default text directionality to set for this stream
262 \returns 0 success
263 \returns KATE_E_* error
264 */
kate_info_set_text_directionality(kate_info * ki,kate_text_directionality text_directionality)265 int kate_info_set_text_directionality(kate_info *ki,kate_text_directionality text_directionality)
266 {
267 if (!ki) return KATE_E_INVALID_PARAMETER;
268 ki->text_directionality=text_directionality;
269 return 0;
270 }
271
272 /**
273 \ingroup info
274 Sets the category for this bitstream.
275 The category is an ASCII string limited to 15 characters.
276 Predefined categories include "subtitles", "lyrics", etc.
277 Categories prefixed with "x-" are reserved for private use.
278 \note Categories are not meant to be localized strings, but machine readable strings.
279 While they may be displayed to the user as is, players are encouraged to recognize
280 well known predefined categories such as the ones mentioned above, and supply
281 translation for these.
282 \param ki the kate_info structure for the stream
283 \param category the stream's category
284 \returns 0 success
285 \returns KATE_E_* error
286 */
kate_info_set_category(kate_info * ki,const char * category)287 int kate_info_set_category(kate_info *ki,const char *category)
288 {
289 if (!ki) return KATE_E_INVALID_PARAMETER;
290 if (!category) return KATE_E_INVALID_PARAMETER;
291 if (strlen(category)>15) return KATE_E_LIMIT;
292 return kate_replace_string(&ki->category,category,strlen(category));
293 }
294
295 /**
296 \ingroup info
297 Sets the default text markup type for this bitstream
298 \param ki the kate_info structure for the stream
299 \param text_markup_type the default text markup type to set for this stream
300 \returns 0 success
301 \returns KATE_E_* error
302 */
kate_info_set_markup_type(kate_info * ki,kate_markup_type text_markup_type)303 int kate_info_set_markup_type(kate_info *ki,kate_markup_type text_markup_type)
304 {
305 if (!ki) return KATE_E_INVALID_PARAMETER;
306 ki->text_markup_type=text_markup_type;
307 return 0;
308 }
309
310 /**
311 \ingroup info
312 Sets the size of the canvas this stream is being authored for
313 \param ki the kate_info structure for the stream
314 \param width the width of the canvas
315 \param height the height of the canvas
316 \returns 0 success
317 \returns KATE_E_* error
318 */
kate_info_set_original_canvas_size(kate_info * ki,size_t width,size_t height)319 int kate_info_set_original_canvas_size(kate_info *ki,size_t width,size_t height)
320 {
321 if (!ki) return KATE_E_INVALID_PARAMETER;
322 ki->original_canvas_width=width;
323 ki->original_canvas_height=height;
324 return 0;
325 }
326
kate_info_add_item(kate_info * ki,size_t * nitems,void *** items,void * item)327 static int kate_info_add_item(kate_info *ki,size_t *nitems,void ***items,void *item)
328 {
329 void **newitems;
330 int ret;
331
332 if (!ki || !nitems || !items || !item) return KATE_E_INVALID_PARAMETER;
333
334 ret=kate_check_add_overflow(*nitems,1,NULL);
335 if (ret<0) return ret;
336
337 newitems=(void**)kate_checked_realloc(*items,(*nitems)+1,sizeof(void*));
338 if (!newitems) return KATE_E_OUT_OF_MEMORY;
339 *items=newitems;
340 newitems[*nitems]=item;
341 ++*nitems;
342
343 return 0;
344 }
345
346 /**
347 \ingroup info
348 Adds a predefined region so it can be referred to by index later.
349 \param ki the kate_info structure for the stream
350 \param kr the region to add
351 \returns 0 success
352 \returns KATE_E_* error
353 */
kate_info_add_region(kate_info * ki,kate_region * kr)354 int kate_info_add_region(kate_info *ki,kate_region *kr)
355 {
356 return kate_info_add_item(ki,&ki->nregions,(void***)(char*)&ki->regions,kr);
357 }
358
359 /**
360 \ingroup info
361 Adds a predefined style so it can be referred to by index later.
362 Adds a predefined region so it can be referred to by index later.
363 \param ki the kate_info structure for the stream
364 \param ks the style to add
365 \returns 0 success
366 \returns KATE_E_* error
367 */
kate_info_add_style(kate_info * ki,kate_style * ks)368 int kate_info_add_style(kate_info *ki,kate_style *ks)
369 {
370 return kate_info_add_item(ki,&ki->nstyles,(void***)(char*)&ki->styles,ks);
371 }
372
373 /**
374 \ingroup info
375 Adds a predefined curve so it can be referred to by index later.
376 \param ki the kate_info structure for the stream
377 \param kc the curve to add
378 \returns 0 success
379 \returns KATE_E_* error
380 */
kate_info_add_curve(kate_info * ki,kate_curve * kc)381 int kate_info_add_curve(kate_info *ki,kate_curve *kc)
382 {
383 return kate_info_add_item(ki,&ki->ncurves,(void***)(char*)&ki->curves,kc);
384 }
385
386 /**
387 \ingroup info
388 Adds a predefined motion so it can be referred to by index later.
389 \param ki the kate_info structure for the stream
390 \param km the motion to add
391 \returns 0 success
392 \returns KATE_E_* error
393 */
kate_info_add_motion(kate_info * ki,kate_motion * km)394 int kate_info_add_motion(kate_info *ki,kate_motion *km)
395 {
396 return kate_info_add_item(ki,&ki->nmotions,(void***)(char*)&ki->motions,km);
397 }
398
399 /**
400 \ingroup info
401 Adds a predefined palette so it can be referred to by index later.
402 \param ki the kate_info structure for the stream
403 \param kp the palette to add
404 \returns 0 success
405 \returns KATE_E_* error
406 */
kate_info_add_palette(kate_info * ki,kate_palette * kp)407 int kate_info_add_palette(kate_info *ki,kate_palette *kp)
408 {
409 return kate_info_add_item(ki,&ki->npalettes,(void***)(char*)&ki->palettes,kp);
410 }
411
412 /**
413 \ingroup info
414 Adds a predefined bitmap so it can be referred to by index later.
415 \param ki the kate_info structure for the stream
416 \param kb the bitmap to add
417 \returns 0 success
418 \returns KATE_E_* error
419 */
kate_info_add_bitmap(kate_info * ki,kate_bitmap * kb)420 int kate_info_add_bitmap(kate_info *ki,kate_bitmap *kb)
421 {
422 return kate_info_add_item(ki,&ki->nbitmaps,(void***)(char*)&ki->bitmaps,kb);
423 }
424
425 /**
426 \ingroup info
427 Adds a predefined font range so it can be referred to by index later.
428 \param ki the kate_info structure for the stream
429 \param kfr the font range to add
430 \returns 0 success
431 \returns KATE_E_* error
432 */
kate_info_add_font_range(kate_info * ki,kate_font_range * kfr)433 int kate_info_add_font_range(kate_info *ki,kate_font_range *kfr)
434 {
435 return kate_info_add_item(ki,&ki->nfont_ranges,(void***)(char*)&ki->font_ranges,kfr);
436 }
437
438 /**
439 \ingroup info
440 Adds a predefined font mapping so it can be referred to by index later.
441 \param ki the kate_info structure for the stream
442 \param kfm the font mapping to add
443 \returns 0 success
444 \returns KATE_E_* error
445 */
kate_info_add_font_mapping(kate_info * ki,kate_font_mapping * kfm)446 int kate_info_add_font_mapping(kate_info *ki,kate_font_mapping *kfm)
447 {
448 return kate_info_add_item(ki,&ki->nfont_mappings,(void***)(char*)&ki->font_mappings,kfm);
449 }
450
451 /**
452 \ingroup info
453 Checks whether the given language matches (fully or partially) the language
454 described in the kate_info structure.
455 Exact (case insensitive) matching of the two languages is required for a perfect match.
456 Exact (case insensitive) matching of the primary tags for each language (which each
457 may or may not have one or more secondary tags) is required for a partial match.
458 An empty language for either the stream language or the language passed as parameter
459 will cause a partial match.
460 \param ki the kate_info structure for the stream
461 \param language the language to check against
462 \returns 0 success, but the language doesn't match
463 \returns 1 success, the language matches perfectly
464 \returns 2 success, the language matches partially
465 \returns KATE_E_* error
466 */
kate_info_matches_language(const kate_info * ki,const char * language)467 int kate_info_matches_language(const kate_info *ki,const char *language)
468 {
469 char *sep0,*sep1;
470 size_t bytes;
471 if (!ki) return KATE_E_INVALID_PARAMETER;
472
473 if (!language || !*language) return 2; /* if we ask for "any" language, we partially match */
474 if (!ki->language || !*ki->language) return 2; /* if the stream has no set language, it partially matches all */
475
476 if (!kate_ascii_strncasecmp(ki->language,language,0xffffffff)) return 1; /* perfect match */
477
478 /* if we specify a language with no subtag, it matches any subtag of the same language */
479 sep0=strpbrk(ki->language,"-_");
480 sep1=strpbrk(language,"-_");
481 if (!sep0 && !sep1) {
482 /* if none of the languages have subtags, they're different, or they'd have been picked
483 up by the first string comparison */
484 return 0; /* doesn't match */
485 }
486
487 if (sep0 && sep1) {
488 /* if both have subtags, the primary tag must be the same length */
489 if (sep1-language!=sep0-ki->language) return 0; /* doesn't match */
490 }
491
492 /* we now have primary tags to compare (with or without secondary tags), of the same length */
493 bytes=sep0?sep0-ki->language:sep1-language;
494
495 if (!kate_ascii_strncasecmp(ki->language,language,bytes)) return 2; /* partial match */
496
497 return 0; /* doesn't match */
498 }
499
500 /**
501 \ingroup info
502 Requests whether future events will strip text of markup or not.
503 \param ki the kate_info structure for the stream
504 \param flag if zero, markup will be kept, else if will be removed
505 \returns 0 success
506 \returns KATE_E_* error
507 */
kate_info_remove_markup(kate_info * ki,int flag)508 int kate_info_remove_markup(kate_info *ki,int flag)
509 {
510 if (!ki) return KATE_E_INVALID_PARAMETER;
511 ki->remove_markup=flag;
512 return 0;
513 }
514
515 /**
516 \ingroup info
517 Requests whether large quantities of various things should be rejected or not,
518 as a simple defense against DOS.
519 \param ki the kate_info structure for the stream
520 \param flag if zero, values deemed arbitrarily too large will be treated as an error, else they will be accepted
521 \returns 0 success
522 \returns KATE_E_* error
523 */
kate_info_no_limits(kate_info * ki,int flag)524 int kate_info_no_limits(kate_info *ki,int flag)
525 {
526 if (!ki) return KATE_E_INVALID_PARAMETER;
527 ki->no_limits=flag;
528 return 0;
529 }
530
531 /**
532 \ingroup info
533 Clears a kate_info structure previously initialized with kate_info_init.
534 It may not be used again until kate_info_init is called again on it.
535 \param ki the kate_info structure to clear, must have been initialized with kate_info_init
536 \returns 0 success
537 \returns KATE_E_* error
538 */
kate_info_clear(kate_info * ki)539 int kate_info_clear(kate_info *ki)
540 {
541 size_t n,l;
542
543 if (!ki) return KATE_E_INVALID_PARAMETER;
544
545 if (ki->bitmaps) {
546 for (n=0;n<ki->nbitmaps;++n) {
547 if (ki->bitmaps[n]->internal) {
548 if (ki->bitmaps[n]->meta) kate_meta_destroy(ki->bitmaps[n]->meta);
549 }
550 kate_free(ki->bitmaps[n]->pixels);
551 kate_free(ki->bitmaps[n]);
552 }
553 kate_free(ki->bitmaps);
554 }
555 if (ki->palettes) {
556 for (n=0;n<ki->npalettes;++n) {
557 if (ki->palettes[n]->meta) kate_meta_destroy(ki->palettes[n]->meta);
558 kate_free(ki->palettes[n]->colors);
559 kate_free(ki->palettes[n]);
560 }
561 kate_free(ki->palettes);
562 }
563 if (ki->motions) {
564 kate_motion_destroy(ki,ki->motions,NULL,ki->nmotions,1);
565 }
566 if (ki->curves) {
567 for (n=0;n<ki->ncurves;++n) {
568 kate_free(ki->curves[n]->pts);
569 kate_free(ki->curves[n]);
570 }
571 kate_free(ki->curves);
572 }
573 if (ki->regions) {
574 for (n=0;n<ki->nregions;++n) {
575 if (ki->regions[n]->meta) kate_meta_destroy(ki->regions[n]->meta);
576 kate_free(ki->regions[n]);
577 }
578 kate_free(ki->regions);
579 }
580 if (ki->styles) {
581 for (n=0;n<ki->nstyles;++n) {
582 kate_style *ks=ki->styles[n];
583 if (ks->meta) kate_meta_destroy(ks->meta);
584 if (ks->font) kate_free(ks->font);
585 kate_free(ks);
586 }
587 kate_free(ki->styles);
588 }
589 if (ki->language) kate_free(ki->language);
590 if (ki->category) kate_free(ki->category);
591 if (ki->font_mappings) {
592 for (n=0;n<ki->nfont_mappings;++n) {
593 kate_font_mapping *kfm=ki->font_mappings[n];
594 if (kfm->ranges) {
595 for (l=0;l<kfm->nranges;++l) {
596 int idx=kate_find_font_range(ki,kfm->ranges[l]);
597 if (idx<0) kate_free(kfm->ranges[l]);
598 }
599 kate_free(kfm->ranges);
600 }
601 kate_free(kfm);
602 }
603 kate_free(ki->font_mappings);
604 }
605 if (ki->font_ranges) {
606 for (n=0;n<ki->nfont_ranges;++n) kate_free(ki->font_ranges[n]);
607 kate_free(ki->font_ranges);
608 }
609
610 return 0;
611 }
612
kate_find_item(const void * item,const void ** items,size_t nitems)613 static int kate_find_item(const void *item,const void **items,size_t nitems)
614 {
615 size_t n;
616
617 if (!item) return KATE_E_INVALID_PARAMETER;
618
619 if (!items) return KATE_E_NOT_FOUND; /* if nothing in the list, it may be NULL */
620 for (n=0;n<nitems;++n) if (item==items[n]) return n;
621 return KATE_E_NOT_FOUND;
622 }
623
kate_find_region(const kate_info * ki,const kate_region * kr)624 int kate_find_region(const kate_info *ki,const kate_region *kr)
625 {
626 return kate_find_item(kr,(const void**)ki->regions,ki->nregions);
627 }
628
kate_find_style(const kate_info * ki,const kate_style * ks)629 int kate_find_style(const kate_info *ki,const kate_style *ks)
630 {
631 return kate_find_item(ks,(const void**)ki->styles,ki->nstyles);
632 }
633
kate_find_curve(const kate_info * ki,const kate_curve * kc)634 int kate_find_curve(const kate_info *ki,const kate_curve *kc)
635 {
636 return kate_find_item(kc,(const void**)ki->curves,ki->ncurves);
637 }
638
kate_find_motion(const kate_info * ki,const kate_motion * km)639 int kate_find_motion(const kate_info *ki,const kate_motion *km)
640 {
641 return kate_find_item(km,(const void**)ki->motions,ki->nmotions);
642 }
643
kate_find_palette(const kate_info * ki,const kate_palette * kp)644 int kate_find_palette(const kate_info *ki,const kate_palette *kp)
645 {
646 return kate_find_item(kp,(const void**)ki->palettes,ki->npalettes);
647 }
648
kate_find_bitmap(const kate_info * ki,const kate_bitmap * kb)649 int kate_find_bitmap(const kate_info *ki,const kate_bitmap *kb)
650 {
651 return kate_find_item(kb,(const void**)ki->bitmaps,ki->nbitmaps);
652 }
653
kate_find_font_range(const kate_info * ki,const kate_font_range * kfr)654 int kate_find_font_range(const kate_info *ki,const kate_font_range *kfr)
655 {
656 return kate_find_item(kfr,(const void**)ki->font_ranges,ki->nfont_ranges);
657 }
658
kate_find_font_mapping(const kate_info * ki,const kate_font_mapping * kfm)659 int kate_find_font_mapping(const kate_info *ki,const kate_font_mapping *kfm)
660 {
661 return kate_find_item(kfm,(const void**)ki->font_mappings,ki->nfont_mappings);
662 }
663
664